From f6d5fc459527654ffaefbcdbef55e54d51fdd8d2 Mon Sep 17 00:00:00 2001 From: lipengfei <15566300566@163.com> Date: Wed, 4 Sep 2024 22:04:59 +0800 Subject: [PATCH] Update Graph RAG Document (#1955) --- .../cookbook/rag/graph_rag_app_develop.md | 242 ++++++++++++++---- .../graph_rag/create_knowledge_graph.jpg | Bin 252193 -> 0 bytes .../graph_rag/create_knowledge_graph.png | Bin 0 -> 95260 bytes .../chat_knowledge/graph_rag/graph_data.jpg | Bin 1015764 -> 0 bytes .../chat_knowledge/graph_rag/graph_data.png | Bin 0 -> 1083748 bytes .../graph_rag/graph_rag_chat.jpg | Bin 255109 -> 0 bytes .../graph_rag/graph_rag_chat.png | Bin 0 -> 466204 bytes .../chat_knowledge/graph_rag/upload_file.png | Bin 0 -> 81883 bytes .../chat_knowledge/graph_rag/view_graph.jpg | Bin 153229 -> 0 bytes 9 files changed, 194 insertions(+), 48 deletions(-) delete mode 100644 docs/static/img/chat_knowledge/graph_rag/create_knowledge_graph.jpg create mode 100644 docs/static/img/chat_knowledge/graph_rag/create_knowledge_graph.png delete mode 100644 docs/static/img/chat_knowledge/graph_rag/graph_data.jpg create mode 100644 docs/static/img/chat_knowledge/graph_rag/graph_data.png delete mode 100644 docs/static/img/chat_knowledge/graph_rag/graph_rag_chat.jpg create mode 100644 docs/static/img/chat_knowledge/graph_rag/graph_rag_chat.png create mode 100644 docs/static/img/chat_knowledge/graph_rag/upload_file.png delete mode 100644 docs/static/img/chat_knowledge/graph_rag/view_graph.jpg diff --git a/docs/docs/cookbook/rag/graph_rag_app_develop.md b/docs/docs/cookbook/rag/graph_rag_app_develop.md index d0a690beb..722fdd3f8 100644 --- a/docs/docs/cookbook/rag/graph_rag_app_develop.md +++ b/docs/docs/cookbook/rag/graph_rag_app_develop.md @@ -10,28 +10,23 @@ You can refer to the python example file `DB-GPT/examples/rag/graph_rag_example. First, you need to install the `dbgpt` library. ```bash -pip install "dbgpt[rag]>=0.5.6" +pip install "dbgpt[rag]>=0.6.0" ```` ### Prepare Graph Database To store the knowledge in graph, we need an graph database, [TuGraph](https://github.com/TuGraph-family/tugraph-db) is the first graph database supported by DB-GPT. -Visit github repository of TuGraph to view [Quick Start](https://tugraph-db.readthedocs.io/zh-cn/latest/3.quick-start/1.preparation.html#id5) document, follow the instructions to pull the TuGraph database docker image (latest / version >= 4.3.0) and launch it. +Visit github repository of TuGraph to view [Quick Start](https://tugraph-db.readthedocs.io/zh-cn/latest/3.quick-start/1.preparation.html#id5) document, follow the instructions to pull the TuGraph database docker image (latest / version >= 4.3.2) and launch it. ``` docker pull tugraph/tugraph-runtime-centos7:latest -docker run -it -d -p 7001:7001 -p 7070:7070 -p 7687:7687 -p 8000:8000 -p 8888:8888 -p 8889:8889 -p 9090:9090 \ - -v /root/tugraph/data:/var/lib/lgraph/data -v /root/tugraph/log:/var/log/lgraph_log \ - --name tugraph_demo tugraph/tugraph-runtime-centos7:latest /bin/bash -docker exec -d tugraph_demo bash /setup.sh +docker run -d -p 7070:7070 -p 7687:7687 -p 9090:9090 --name tugraph_demo reg.docker.alibaba-inc.com/fma/tugraph-runtime-centos7:latest lgraph_server -d run --enable_plugin true ``` -The default port for the bolt protocol is `7687`, and DB-GPT accesses TuGraph through this port via `neo4j` python client. +The default port for the bolt protocol is `7687`. + -``` -pip install "neo4j>=5.20.0" -``` ### Prepare LLM @@ -117,10 +112,10 @@ TUGRAPH_HOST=127.0.0.1 TUGRAPH_PORT=7687 TUGRAPH_USERNAME=admin TUGRAPH_PASSWORD=73@TuGraph +GRAPH_COMMUNITY_SUMMARY_ENABLED=True ``` - ### Load into Knowledge Graph When using a graph database as the underlying knowledge storage platform, it is necessary to build a knowledge graph to facilitate the archiving and retrieval of documents. DB-GPT leverages the capabilities of large language models to implement an integrated knowledge graph, while still maintaining the flexibility to freely connect to other knowledge graph systems and graph database systems. @@ -129,19 +124,23 @@ To maintain compatibility with existing conventional RAG frameworks, we continue ```python from dbgpt.model.proxy.llms.chatgpt import OpenAILLMClient -from dbgpt.storage.knowledge_graph.knowledge_graph import ( - BuiltinKnowledgeGraph, - BuiltinKnowledgeGraphConfig, +from dbgpt.storage.knowledge_graph.community_summary import ( + CommunitySummaryKnowledgeGraph, + CommunitySummaryKnowledgeGraphConfig, ) -def _create_kg_connector(): - """Create knowledge graph connector.""" - return BuiltinKnowledgeGraph( - config=BuiltinKnowledgeGraphConfig( - name="graph_rag_test", - embedding_fn=None, - llm_client=OpenAILLMClient(), - model_name="gpt-4", +llm_client = OpenAILLMClient() +model_name = "gpt-4o-mini" + +def __create_community_kg_connector(): + """Create community knowledge graph connector.""" + return CommunitySummaryKnowledgeGraph( + config=CommunitySummaryKnowledgeGraphConfig( + name="community_graph_rag_test", + embedding_fn=DefaultEmbeddingFactory.openai(), + llm_client=llm_client, + model_name=model_name, + graph_store_type="TuGraphGraph", ), ) ``` @@ -155,31 +154,67 @@ Then you can retrieve the knowledge from the knowledge graph, which is the same ```python import os +import pytest + from dbgpt.configs.model_config import ROOT_PATH +from dbgpt.core import Chunk, HumanPromptTemplate, ModelMessage, ModelRequest +from dbgpt.model.proxy.llms.chatgpt import OpenAILLMClient from dbgpt.rag import ChunkParameters from dbgpt.rag.assembler import EmbeddingAssembler +from dbgpt.rag.embedding import DefaultEmbeddingFactory from dbgpt.rag.knowledge import KnowledgeFactory +from dbgpt.rag.retriever import RetrieverStrategy -async def main(): - file_path = os.path.join(ROOT_PATH, "examples/test_files/tranformers_story.md") +async def test_community_graph_rag(): + await __run_graph_rag( + knowledge_file="examples/test_files/graphrag-mini.md", + chunk_strategy="CHUNK_BY_MARKDOWN_HEADER", + knowledge_graph=__create_community_kg_connector(), + question="What's the relationship between TuGraph and DB-GPT ?", + ) + +async def __run_graph_rag(knowledge_file, chunk_strategy, knowledge_graph, question): + file_path = os.path.join(ROOT_PATH, knowledge_file).format() knowledge = KnowledgeFactory.from_file_path(file_path) - graph_store = _create_kg_connector() - chunk_parameters = ChunkParameters(chunk_strategy="CHUNK_BY_SIZE") - # get embedding assembler - assembler = EmbeddingAssembler.load_from_knowledge( - knowledge=knowledge, - chunk_parameters=chunk_parameters, - index_store=graph_store, + try: + chunk_parameters = ChunkParameters(chunk_strategy=chunk_strategy) + + # get embedding assembler + assembler = await EmbeddingAssembler.aload_from_knowledge( + knowledge=knowledge, + chunk_parameters=chunk_parameters, + index_store=knowledge_graph, + retrieve_strategy=RetrieverStrategy.GRAPH, + ) + await assembler.apersist() + + # get embeddings retriever + retriever = assembler.as_retriever(1) + chunks = await retriever.aretrieve_with_scores(question, score_threshold=0.3) + + # chat + print(f"{await ask_chunk(chunks[0], question)}") + + finally: + knowledge_graph.delete_vector_name(knowledge_graph.get_config().name) + +async def ask_chunk(chunk: Chunk, question) -> str: + rag_template = ( + "Based on the following [Context] {context}, " + "answer [Question] {question}." ) - assembler.persist() - # get embeddings retriever - retriever = assembler.as_retriever(3) - chunks = await retriever.aretrieve_with_scores( - "What actions has Megatron taken?", - score_threshold=0.3 - ) - print(f"embedding rag example results:{chunks}") - graph_store.delete_vector_name("graph_rag_test") + template = HumanPromptTemplate.from_template(rag_template) + messages = template.format_messages(context=chunk.content, question=question) + model_messages = ModelMessage.from_base_messages(messages) + request = ModelRequest(model=model_name, messages=model_messages) + response = await llm_client.generate(request=request) + + if not response.success: + code = str(response.error_code) + reason = response.text + raise Exception(f"request llm failed ({code}) {reason}") + + return response.text ``` @@ -187,26 +222,137 @@ async def main(): ### Chat Knowledge via GraphRAG +> Note: The current test data is in Chinese. + Here we demonstrate how to achieve chat knowledge through Graph RAG on web page. -First, create a knowledge base using the `Knowledge Graph` type. Upload the knowledge documents and wait for the slicing to complete. +First, create a knowledge base using the `Knowledge Graph` type.
-
+
-
+
-
+
-
+
5mP)F>|-7hr6j- zXa(rjH3d#M2|gR(V-wQ){vTMq(w2a8y<4Wo2duX1+10Y%s4h{fE)T`>WX};A#+Rjh zq_*Qg-=nR0d}1@pgjwsPW1P2AYKg4OR+_VP-ypQn9MEOrlJutOkz`YN2jZ5ZIx4rBDem*-VOnMrQ(0^^Z?uPZ_+@pWS~>G z27j4YIy>G0jf9*dx#G0*oX_JMWdlG}RoQ(GjdJYuzINW-9@|Ol;~6JTe|cu)w K6Y*Hc$}x+9Ul@YUy(EPoV{OzMfX3ww1)eWn zm99gRuB!JgfcvzLJC-!U15^L*q5RniX0xIX$G3hUsM>~uWG{byO}s01``TTa`4YWr zqt rPGADvOaF+Vn9cH69UuSw7yO%_h4A_fYB5AfgCn68_So=^i`#of z0>3_`Wg7KLn;nebNmw(!apyP4T6Yu?Grj`|!aO(lg7^We-im-a%AU26Qa(EWDRY@~ zhmCjHs0uq!$=c8zeqVmU4x^)cmufk?Qg)-mn^3T?M3N=myAzC8*Rof5_;k2k`Bs5N z+jOz&?B|;8VcENVhlqY( 6mZBei z46UK={2N5mL7ESk#T$0d&!-+lUkI64h%~5+SZVQ;VnFeHJ4h%_HwA5|8Pf4TY4icq zVK0^u@9pc5=8okiw(7< 6iu#`>(jKdS3_wD^d%%G_7me0|!s;wk4zC%-|bPZMb4 z$lRzqrv|JEoA2$P6DxJr)B<*;ujo>RR3^;%FimN8(n^3JxxYan(QpK*sub=7$bW1U z5Il`*hZoRX#?zUq8Ivvzc>Vnrx9!iTg>Tq79EMcyG(NuRm)^cLp|+oVl8!n<3T?~q z!K|uV&*61OHf$~o3pkjIgb)sGyq;LtvGFX}3x98)R~7n1a6wFs10tp{(k0pm$hD`{ z^3zV^?)hu6Wu8kNk3PG2bJ%}FJ xsM6pM3 zAVw({Npb{{cH~*|S+TM)vU4EcozHo$E>>b;9T%FleqDU^&VByLLTSGi48Yc2lx;zV zqu5E3E=1c_vm_VPCE~40|L~b#8i}v5%2_d3c^V 35) jl# E2+rDYq@@^s8O%{&wSuaLtn>sPk47lGY6gY!_a*aVCZB>TXg=TMkBC5C0`M zwBP*k8$+5GQq*cRy0WkO&C@loWG+G6%uXweeiJWdk(1?WI-f*m=jDXgvwz$|^MY<2 z_6c$kK%QCrKyTaz3LtmdgCOTmqL3~u>< 8*oo={@j^P$^Ubnb9 zq X4RL|G4S=U^dIf)=M6q9eA#3P-cG%Ku1?FFCdC_QW^tBx_hdiY&7H-dGa zWw`+48zD}JA7FX}n=ds6eHJ3=VoZ8M^tMn^bKc^}m(Ty!#+bx)_GK5J);kD2 B##(#3DD7Rl9IOk)pf1!WSqCS<; z|2JrY9Yc{L!HyAREfObg`URk2VAN!7$aIab=d&YqSCYG{z>T=)cd~FE>*J>y&0s{= zY&;U!yTXL58bXt3 P&YM&)NhC0i{0wz{t}v46oNJuj5d%70pEtvc6VFcV_l~2aSI?vJ)wyT4 zxXhimTbVHECvp}ktg+op-(p`^z9%LiY{yWw!2DzYfcEzD%WdE=*l7fxOO2%~rRHsP zd2KRSwaOq0FU`R7hK*YHA}xG8onC|B99K1<|$<0mr0|$Lb$smX!AiQe>X{ SX`D6OKFk@ zHvFv18{p;hNtYGDlLjqNc6Ez_0px7olm7mh4b5AP*^g^q*4LPI(&4E;YuDN(Bf~O4 z%Md9_pN;CtI|>*ak7PkQnU2Hn >rC1$pyEK#$VNWTqhbwdj}JI!15Cy z&B0IMyiS6p5Gs?0cYSy6H2`wzp1t?aT-p LOdfsL@C0t7i`-)A_+ zLO{Om7DMWi_PCowYRh#Recv%We?7bgBwCJ>?~P;Ls%4mW?gIfefeP$K;PG9!CqV;^ zrx$N$(r)!1D;$34jDR1QvH$wwcD+lnNB)iRv>`|za+moRznRi8 q_;A#u z&kQDFYla^@EpqGzCKm$lm1 zyX9><*-)`lU&cs9yC{2x(uL3 NVi&aZhQt!0Q!hcQE z%YSb6@&d$So+;rPdNQxs9~*_9eUGG8x6f}rP^NHImAecEWlPL#V|& +^FZ_Dr{eo=>(^%m2LiKYkLZ!%5*phE{-}o(#R%RI0!BO*7vwr7MAzc1HuWFdhNdAO+x9q6LK# zapP@;CwvCOKfy9|M|t(&Ug|EW!b{Fw2zqvlk(4`cR6o8;DzzUG+bQXdeV>>(>UCA! zjygf|Qx3~(lrS7Zq-{l>Ga$OmN!gSXIX`7dSGVY?7b17^hwjLF*enwcaNLm;QD1~~ zfL8jDV{qb@Pzrxu;(|YG=hwBm_tY&jyo9Fq58gS>L*_k22Fni>T>yOlp!ZdNyOabc z>QDc&Bukqw)thZCBB*X$I<+Qv+OSE2W<|n#Rg?XGUdc@p=1MBDKRFsbiEF<9tX +b1g}RYaDQpoWL__sl zIXD=09jLwwlMeP-Pf}5$zPa=5HkSyBy7!wr#d;>Ktt~`1F%@bZu2RlT(PD2dIjAS! z@iK#!b!?1y;Ghh?C2$sZ*U!F}rBn1=tYV9uO2R+3PTzpPanQ?utR63-7}eIL)?+rJ zSV^^%%|T%%E0D(L21qv%mz=ncC>f RyYPK>tgp{PRv3O1)%%!iLfCvDVR<1=t3_$AkAn(mRG~*Ol9fo@ zbJ1` !>mF zx3BTEfLP}O<9IDF<4UBO{p%-LjXtvj3}gt=Cmefk5YCm{mT%Sd`6*S2ZKm5ITS;^3 zINb;BhSPUBpP!MOmT8pzVB>2E5cy4R4HZ k5pC%nqag32^BlugV%iRaLBWmpw`sR$l+wsi#3P zzD~bKflIYZb*XV@c59=RpfJm{|M4?fjL l|L$N`}(D0XI z+%mP`!A+2_ZX0+adp5m2k= d07ObsqmCVbo%CG?kq%V(U1zLCk@f!922 zqUW)ZS#+elx#C1RxYm$s6<%;9WdGoDosaCax4Qh*jc#q`_67+{5GfHLh70jVbP9rh z 1tkFpPP@_KH6S7Ewp@w_oCe^|7dFJRhUC{>POTYFWrjp%B8TWOxyEsZi~J2 zb5M7ksEMy_zuGQw!a+s!1;z?Mbc$e*gcRg=ROG-8e5>N*>()lVPBv+Or?CXRJK)yq zQNwRm?CZX7OX39*KG6qYUbw=X*9h6#>uaKqK;KwjvQT`gYuu;lGtC^Q<3O}LrG5bZ zrrl_YeZIk0ZC=WT^Q3@6=Zv~c^5E}REP2XfckER?d~rkT#jpguac!DF*E`1`)5K1s z07VLZ35d7m+?f#rurl=b*l8KnDyJ%glIkQ~Zx0U+`6*1vLYJJ~&G$V$ia{6EWbPnu zDNMC^GfYk2sJJoDnDF6s;&qlYMXQq!((|TH()BAMx*3;yLX@KA17A~V3R)9<<}!T2 zvyNdD4&U5MO0pXzT;q4p@uLRr3SWf9O}@}M^| ^Cg zV$vWnj!K}g|F?^(?9XeH4`LmTA}ait!oMI9F40_<#@G5aIq!z17{@el >MUMdCs zKtDAKx+e9BZ-Cdbv!_LQsLu->s>K(2IFwHrMT5NGhAAWDtK#3xt6WwpqDZSd(Jlkt z&{1CIivXjd`-@v$l7ai`So{~TifncKp9Eg-!J0(G+oDzf9~n=tDJ`h%mj_OiELhmO z=Lri@yg%5`%;J98eHpkVf5#fwl~p4DJONIG{#@*dZTL|JC?n>>$wxbuBkUkhXS*XX zU0FbXA!YR)xO4Dy%;i6&TL4gZ>!0M}k| V#y*_Lj&()f`%517P0*FoRS7EEl(v&2xE^zMmLMd>;K0+>v<%Cgd=Tn%-!tdNpUy z3u#1Ns{-uFzpUr~@e4q=^slH5=f(Nh|33ZT{q^CXi=TBZWAX+5fn$Aj-;1cp@V}mx z>c0nn^9LI<`v2dkE#}st%6=tjQRO@AbVnZPB~lWD5@Hc(NU)qd-JFJWSdc>E+59GN z2JoKIg~_+yYk8cytm1BnKNKszTEYK4iz}@7hrjMoP4CigkW=a8x&i62Cp5H?iQlp& z`Yvadu3E{LOaVUkqb}V8`BMP4W}pX_DyTpTorgvFXFjDUjL9fjh3LbSeuI1j19W-5 z>u98Ee!XsCmt~gWAg?bh)!QLjwvcQjnqiOhc@B%LLm1rD3F9d8&a~Ot-Dphj-@11= z1;ITtgt(5T<_$~QQ``r(0g^b>%Hez&!4U&K4_6-@HzU}Td3=0$ios9zxK3_Tuir## zqdDfp{Nz2-r9>7N*el3H?DcSlh&|_`KZmbwdgk@;H>mjaZ_x8(K9V8AlKiruL+Vv$ z%Jn5x5#iL=vmvT9tb;Km8%4r_Y=2?xcu2fqiouLc(|F3E#abY 7w@*MPLB!g#NB!t9PjUjv zD(-U#rr3~qrYU3F bdVBbzu*<0k0k>w6;JsWee9c C9jIjZx*VlOKVXT50w`ZDqiYD8Dr$(z=Y6X63yU_Vk&Z+za zeG%88vU_V1*Dg_iDF5M;#Mw`!!B=)PHvQatXw@v@=COK#RFg&<=-JT!o*(S5RY0dl zEgmF!YRB}+?U#)#TmC1Pm8`y7ZIorv&Ky8eqcxcw9L3%(WG!dhx^)Ru{PG}W3OrqH zc3klBer}K&gF)x!h-7O*v6*CKj9G-1s3W6fS ~@s=k0|BUbUe}#+u dIHYK-|;dU=OxJ^PreXiL=?! z(&}=!fMSD&%!V6{W);qYR}w|qspLf+U)pMv#d(^M#fjJs2o1?KfH2>(!z80&xNp^y zxl%6k)-L8!nBH&DcAsvVzWrf>uLRZf7ObWN$_a;NAAta#u+=+l@Y4_H6(am}8BBE) zFBVxy+Z}QQF72Bw4asIgl6m+=%a2lXrap7??HXhp$sD`ERe`U7%~lSiK9(gdxl_Si z2>7ixCL{OXIM-;aE1KB}NpF-tLz0*fTjM*XkG-YC_o{Yj*`_*^FN0^U^B{83A1x_& zj&3e~i;!iAF|cSiM((fQL9Xg<%y8pAN^ll7<&GS0QLdXUZ{eZGk4ZHE-pyKJKafN< z_jn!}eN-g+>2k1gT2kl7abL5ziVZ x6mx-RveBW#=RTt<~+n1t8JV3Rbr6VliST?vU5jjVRCQ7!X zC{99}Kw0cU3>VI|395obY2$w+HH)6P7vev@TpA9Y{RFK*VtmC3-0j&cFkh`I8s(a? z$&zxcGe%Fj(WIP3!MUHWH~2oYKK0dI@DwDFeXeE$T53aP$O1F2dMIZqzgLM|;Cl7N z%s)(KfO;~O&z>2Rdeyb#s}uF^`53Yn>E5vdWiY!6{C%1hm)PbWS3e#;Wjum!kNvcI zM?8h;i*b>*w@37NU)pn&t=*Pdu)N&{?D|PGN(OF2=x9gsBLK*-fOjO3t90%XV*Jz7 zd#V5qHoaTz{DYqQE{-7s!ENg^i%$@DbHJbPn=LLi97|9}!2A#)Qeqoe5F#;6Qu#jA zuM_{#*KKc1u|{eNK72!u_r8pE>cr0)2@oyIz5@}7*$PEg^;aEBl4?4}p{#Ie CLC!^N%5W6KkST%81GA%7a)0E%_SpJvIoz zPgeD*8Qt97_o}U{i|#e#vu)qzek)*XaQHOpVaQLWpKSz{{nC>(lo;urISGnua>sQ9 z?a_~6Er*q?!jlcmRZ8EAUUyEV=8) gc+M71}cg-3FrI&j7$$;=T$YA0~)8 z2Y2}aH>~GuL+_*B7C+>jtBdh7k)APov$kfPYH@4J^vSxAq$ap}uLG_{+=_s3lO)Ya z!SiZmws}r3@g5$R7w|Tx06Z3Z!@0t|v?rj2AF%Kl^)gZ(VZIg0>h&{@iy}HwQaX0w z#S?{gfjsfJ*H7+eEtoAEkvU5-=Tp<0VN9ea-?jPue}kfg^^a*2=)}BrAXyIWM};}e zj;+~MM);v)J*DLssKakiq@_*b>>K-JNteFI!5NFWPnZSub9Kad9`ipdoVX`^p^0U7 z3tvM7Ym+`Z6ZrO<31J9&qG1tH_tR6ZoRf$(eZ!waiEriM_;8CSNh!$g7CNOP?pY-5 z3YLW|kn0O>9sF|ME!^?+JGwluDBU^s1bke|XtMrN {AenFP z{4`?1j8$CUcAbtEwtL1F^W0EAXD^4vEf;+S=_(tC Ih3! zp9dZb^sMgmxQeP=nLf!{WE~0(bJUSgd6Dm^WbhqY?$}W}$ugG}PrQdyX~zd>5t*9` ztYFR=FEd4lR*&E>u7CQe56<{9%+vkW+%*uh_>PRB-b10qcENGTsx7<<5hy}NK d@aHI!{gENIrY+)JK4r0kx++>b}Rs?gR6#zMOXXsK`{k~-EFdXG( zxF711W+lX*IzT<#7>aX`f+$fYz*X+iP)BT}jeI=;90U<8zWCYa(Pqj+BVPK8M85W6 zh1<8C!pT+l< SCIpP#E+%f-MiI{t#$;ULT0LZtIgK*HRJ3?N^_!ILkcJ0rkB37ymA zE-Zrnb?Z*ZJ2vc~_#-08mrk8 Vdj4a&+U0cgClpr)I~f8DPm|1sF^ zpP^QY{>{j``|lIUy8xSn5$W#fHHpN(Zms@hv=4s afhAz`)DUDz*t8Tk$;V4L^3`pu>B3vfD%V2KztLE_t!0eef-B*D}RO>y8o{O zC*sw>hrs_z$o^Y42K?7;&A$w$4UC0|DP~%1YTXDwxWc=l3y!z^Gp#Y8Vn4Z%NqyS8 zS0Dv3^Ti*>=(+NyBe#`$aY1K4Ba!wWfBt&v|9aKM*_qEkvHZ%71jW;D-zI`U^7_Tz zUB2rr^)L*W{;3V)*vBkBfd_INeQtAN^tEzlF;{roS!m+`cw6$;{vhEw_q9*4e}tg~ z`OAIus{#Uq_l>`uEIK?_J~-@V{be>P$VkkNgb4Y%^|WPiG+Iq7ANuIbp3|ab{916@ z!ibSY`yqF<5)6bGK+|IUgBU(Iy>xLt-I#eh-M!*zTO4Tn_6zfQ{tEs}qJE_twzGZ6 z7Ay@u9V6G&Sl{<+GERBx{oqt@VOgA@&TQ5r!T14H4yrvs8&Xq1Fj3CQlATN|vf|=U z*Tj=ud3D1KTKF|N=nC2Bb6+mW{lS=Ps*MYS{w6C-&EO{ARi+STdj8q*ZooWL9qW zbQ58O@i4FA9(s#ZyB+n$*H<4`8+>$QsR~pD_VXdDy6$h#qp5)tw!H;x`4%~u2}(i9 zpm&{fn0*XRK2)JuNFmr(Bu}H_3|~M+)aFpE)@sVTkf1&LmmMAnE^B}hlz$i638})t zDpew%0f~(8Ya`P+3eIJ*wfqUjIH7mo{d5ULRWHfp7{?urbeyJYWKuMC@zj)VJdT)J zY@=?xIW92)7orwHZB|n4zP~r>Ze}>LSw(BI?!w-E|GC~x>EOLKcw`BglL(7cm-E5h zBXXMvid5FPMD+E1kym$V%Hs{hu+h;F0!p8*RvvmA#lxtjs!9yZ>W545T#K8c z8TV&?KkreBZ53$x(M%c8*Q lJf(M)}+ii$98M+IWkHt8 $k$)G`XKYW#>xbAl5_9CZC~`thw64^A(BniH1AR zqhs!pc?mk7j>MWO4V3eISTAVuYQN)@n7UpbRMhIJOy8WtQgW#@itI5f8wI8D`UoIt z!{CntinN{(Ps+!LZ}aSvLN+DLi%(%r$< cjyT=(3@UT iy#SGqlVPI;6P z^V+i{M;jl108|Ta5{I^wqR7V$jd XeRAJ*ccva{n8oNQ-Q7 ^P hOnSlC;3wU#WNkdsgQYY-pBRU=$;!NThQW}_t1T!RRR5G~= z=ABEmeZg=^G>+}6hGYlQ39!sPC8YBQFl)=rF0TM*^Qr5{kLqT+Fg;}R4zT4i;xt+Q zwXZ}6hRrwSp6_0~yg8(6`CACKe;%$0PE7}27NE~zDRL@(`x^u}dTi@HTo7S`Y|Q4z z`Z0AC_{xAnMT5>l>C6*-s-e1Fk;%_alhsx8=t;GETs{Y^D}v{0w(TNREgq-MpZ2&w z9im;a2j1=tyhOeBRC4w`4cU-5-Uj0*fo~GU`qMumos7i#`VW%zgd?1dg= TA%R 6)kbZTy@Lx^e|8|@D;V=6PnCpM*k$`M+ z3js3lzq=^j= &R? 51s~4*=T*Zw0NWWsni0M!XvFY&&F(y;()o;W2d{vs2A;Lxp5b>G}m){`T)dMEJ z;)eXYI?3vB->9pyU6h#>Mh5TFzVWr)FC%0X;4)cgNgb{A10khV4pR=3O*Ki3m{;fA zM6XEcQ7=xV#Q%yp`h=E4$iS@$iFjQcl$I<-V7=xSdOu-5(8$<#qxWgi-43@e#|ud{ z3zw*3C1zREU?X4dQr)xae*9Jp{2ghy$HYN39h#J6aMy~>6(|1rCdE_( 5k3xqO1bK!P!Ic4)FF%LAu|d zZ;yY2rn;BN0mbl}jVB+(3GN|#e$NsL963}S9bzWsV?`@O?eNT;hRg~nEi@q@$V4eO z=@9oDbk0{~Zo0i`E;Gp)o_ NxLR=5wL0|);8o}a8mD2T6OG7MBK zo^JKpcyL3U@uy68Gn;%I3$Jkb8Gn}etjn?O*oybrF;BF>`*CT>*Qj45(@I_l{UsT4 z8Wd=dGi?<3!Fjw!8s!q}Wak+q-yf6`+`KSW1@9wT;gri}p%FHG6@>mXHKjM*U7!7= zX{Rx08Wm))D~coTI97Rz@B5P?>Y@AJ;hLi?G0J|mJ9gWQwbP64*ap5@Y@E-;WDo?E zi}EE&6UEyE)d^=l3yga7;NCNKJ%f*wtA6}>Tl(VA_F}MEGlfm}p_#Bf0oqYNYO;=G zg(CwUi*Idorg^4@2zKjUg3eyzV6myB+H2z60XM@0Tq;^{*t4V#<7@A-nBV0zJ+b~6 z#!Jn%ko;4QjeeQtg@=vv>@;5ow(`z?!MuPKCf)x`=;>B1XBVf17dgrx#=OPTFBaG^ z?;bIOG}3Vc35`Z`$S5d_mo(dkmi^b6LzSdALuAa( Ez6rEIC`Gjyv!^wkYifv7Gg zcV39khkmCg7v0MH%x__k=)QD`I>kYzEi<{}V&+YroKv-lQRs7URYJpe?ioem?JsG{ z5)i#+XZxfCwyUG5r+*TtgnUFndieFZ*gxD)S)`R`EL#+QxMH^aL9Fo)9UTn;cAib; z&`D!Wunw7z)G=2YKf_y3Gz%|r!%Mr$3U&?eiRd#%^S@xDd7-C_)559_2n>{%wV}Ul zkyEhT$e$xX(_F4}F<$B}l~sl!My=VOwKgzdOu)(6k-JdClUzvs pppV9T9TiVqGzG!ey(Jn-_?`asA4Y{ zxZayBrK|}MQK?;~hF;+_XMXO|zsrXPQ~E5&${u^pbtw%n!UmSbM)}G)>?C PLxLZ9`MgHMyNJ(Q0)eC?&x;7 z^OLe#?+rqDNnCT!l-yZW20Y(?qEm6@vm(9FW@~-Lop8tRAQr+&YMsMI7W~<_LNJ>( zf0Mvm+~viKs!6Kw%MP^E@4xc!-=&@0HS4vxOj`DKCWsr6!auc_J)LZy(u 0+U#YK<-I56f>EfxW@-&{gvB)PH&6jHug$<|8LM6FIsA+1(5FD zKi(_A`R<5hB@I{tE_%Ex+|f^TJk92z$#v^Exjw#1_r*`QzTVoYp&p5uM+mIK&Y{GC zPRmJZ($`~y!CkzLS(@I*q_3imKKH} 43E3Dw2<=Li zM25>9S2m~8f@#tH>N$()Jh6oK@A8lM*+Z05l8_yiEU^@-r~WLlyJ#-#+EL&%uEo#Y zPvq(gE!)&zrlCU5?A%PKX!b$JSuux+^NI0|_u&RP QF18SKnzfPGyE&ZJA;k?}g$BahKy>ZGg}XEY&` zxhOqS6Oq~&Xk2o{OSVr+W9seuKPZ)Xx=OZp&--@=zYeXumb4XY;7ahpu_RQ|shi?h z__06NRR&8iTw|N7F0M^4qARbcQd32>^dk;T01M!k-I^Hv62^+IMs(PVW$!BuRUzd< z-5+PavCY9X2FwZO;h?c-hAJqdZ;E+C8Gv4Gc{V;aP`;3FZ}+fv&GWVRXX =^&}pdoM52Qf1ypS>5$p7lawUtS4}&S60nmS&?a_=0iiiRxCI@t>Li z#~lc_gyY;?^ex;z2G%`k2A1pVQ&XC}E#jPu=idQ=9`Af9gUnl8Pf39GxXgp$rQvOu zB8GR!; rA*sbWJ>|m(l9R|$0q_qn-LED`s zB}G_4k2kjNS=wY#M^-+_g+Y(RK%~Z;7qz)Sq)n`ngq^d|5vNO5O*rH6DlD36J`O)g zt4RlX#Zu-}`VInuYZ8@FN?2+V&PeSc0Ykah>+$xUr!b=~qw%YFEaq&Mp*{f{awLv% zk2%uGvqj>LPgHJvYk0B6F|70hQ=XeB)!Bz}Dt_nHBgp&$1l7D$n$XBA8%yCJyOxt| zKd+~s-;Dk`r8ub6qo8<0DqOGY*%halS9B(HPpH}FGef2S*_U zGruF$i7XM0Ch?zOznW=_^5ZxXpVW%{9N)EqrC@8^zZb{zwN;}zc02V)_S&oh+Kn+j zNiwXNg9bc22RZ}Buts0%>{h0X`z@m{P4fy!c||Zq?11)8DVzL+>35w*v*x{BB;gsH z8YqzNYmuDHej#hn (aL*Erb-2jiUXK;q&px6JDz `>J#o$7dN*TPUuY@EpC#t9szwp$+?DN_L;$M=}~Z8qwaFHcmj}QZr$q=>ysavP|0( zCf{#0qNYZMkS(=lEr4iM4Ojduax&EXBpW5Sdc{}eR*YE6?Qu65tIh`bFsH`8p`sfJ z457j=idOEvTLuT1y@Fel=n1j&sC4&y@&m#&s(~|;t0pN!&oS&<%l2}3vMFs`p=$xP z(5%_)@=8Hhb`5Yk+usS8Rf%?kdwh1X9IHKow_aBsX@TVJ?`!Wr2>u`~QSi316ZvDK zpTf-2VU`BD2qfA=pq*J4E!g|(YSOyw`{(R0R`A{MTXwN4fB933{|O3DK$F>#`?>^F zm0&fBHRXOXH !|)Hbp25%`IG^1>HTPyWx3kN@g2JJId1iT(^-KZqz99H2?^S_89KyY%{3ZDzi$R zdQ^UGGv=nLz4!e40>-n6nNUX~Hgren)DEtoV=HnWA21ispsTE$Qhw;-`TRo2 ghw2g zJ+@t;U2>x|;x~u^1ttp xZe8Yd54GYJ)@@UQzjpz8DaB1(Mn5)#N8?f`Ly~ zs05?VQpSvZ^KeG^0OAFgY;LQydly!@>x-O+tR^Ky4nOmUT}cd(KOI-3!%ky2R=UyZ zNYFL_<~hDKmoo6EYxYFNps6Ndejs^H#*J y+XGGfi# zKwHmGvWCn2I?!dUp>ns$K4K_kptdeZee-%@vRaxo2ETLegW5Mqylf1thUGhy%6H^D zmbp<(h!l*2a?FTjSg!ay*ok#a9TM4DU^X?VAT&K^;AeE4KwO~=fX|>bCZ+&RDnc8o zddz}rCoP%bjW&O({;b`r%OYYvt{N?0ZRfZ*5|1_D3_pybAbh^p8JHgC>F!S~Wo*uw zk{%^K-}dw47sz~ZRpSl_@sKj{8^nU*cShGBBh zw~FiHrJ>6|SNT3fzv11J253z7DdcQAl8!9L9lh75xz^>?S-oGcQ+;sY8A(x0xQzZ0 z-1Sme_x7d)%Q_fS8jfTE7+#;k=->u}C3`0qb+C(u%*M?^>L$V#BG2iml2U`jvs{|h z>5tD)x{=I{TJE?+7GEx2B}rBFPSK{iI+WhKz~Qoow}^{I5^V<5ovJx3UL=(ql5H#a zELk#_Bx}?#>~%?z#Pt3n@!}et9Zb%|wHI@hDS{@MMWA?LfOJ{5W!fEw-I(@)Mz{j% z;)L)8|8A{wy(wB8FK#|BQcF$HzDO(Xa7Mr7_$UTMYTbvOlmQm{8Oc6>?R-u2GsQ&C zi78#KlE(p_0*yT$Y{8;K(Y!uw!hAo{g{Z5(HOK5A<6t$eCE0B-dN|ifrgY_26iRel z2E#qvA=&5X@Z~ maX(Jk&1nX}m&Crq6rtGU|Bp5h-29)2QSo<0%@FW-K0 zw7)&OVO^Z%k>y0aGqV3~T=*m#=>Przr1LdMZGy6A*00$*kIc}>d^1=aaJ?9)UZ!YL zt$N7{^e*N|d%xkN2tl_3t|*8T8Y0`~uTN&jc*QoU7*>vy3N@xVqN8)zHsYsPb$BWi z;ElFv!baoha|k{XH?B0IfPlo@VVklUmZ5V9SyVagy|U8Em>~bWQyU1SmIi1k&ERs! zV6ql%bS3gsn+Co(T9~`W% OIbC? zY7P#@>SM3ZMkJ_B?MMlQc3!*?r*l;_<|K)v@f#$X(gNP69zpJ=T|;7kq@fKJsc(*# zOiL6up!^*CY8PW6-MCtEpe|j (IGW{ez60o1LE?d}0 z@M#DyTog?d1hQy4l&(6W>jZifi|1xP$z7 #-9QY)PF3k1-vr* #veyY(#OKp}xVb2wss2&5U+pXbAnnH|8N1r_i z_vTWuZLzQfmGjD5d=`^@bX6>s51Fbl*IsYaWNFP!r3h~N@0Nz5U9#g5ECio61NYNF zF9p32k^6hYo6uE=aKxFqEXlX5x08}@`90%(c&$U|MKGAgLsJkSwK*+uQiS3p9nYx) ztR-CQ4=7TN^-UqaLB@3>KOb67Oj_~F9Hv}G>Awd}8iItQ#IzBWWWnE{Wc}I1W2#m3 z(H#MVFx-ZSZbrx3Fw~s9g+7KwCg1t&n{hO@Y|<3dIdwtnsllZTzv$QDaJJ!dQB*Br zwI{O#L?{r_l!kd3G4iT!ZN&1qXv_xz!CJKKGzs4a^78suhC=DTGk5*BKX6zpwCRhY zu(9lZwQPvInRH%xr8)HBLqa24rO}T&pqu7`5=5QY*;3{;K}jNK$As6k{KX9CE9T)g z&CCYuL7;`?)9z!4l6+^&&1~hQuNGQ`=D*_0r+(>_w+Yb-$zPSw(NqT%%DM;u7IrHV z%8$5!{N6>H!Wn3Yx7IVZc|n Ccgx+4EzTDux2v(R&%UT`{1~* zC-9DS4zn(R$J)N&n?h-+$vzS*ZvF$-IZsl#Niwyy{jxsB#Vt4R!csD}FgHo-)vH?# zr{q;R_n1!NzkYt~`3a`GG-cgR=zc5mLhqxw-8mhtHD;G~=v*e`>~GK@Q1eXj0f^^= z)EnkY+nM+ 3(_Nw-rW85ZC !Ioek7n`-5)D3eKIxKPTk$% zub7{@`Zd&gP|=;;*>k1-B;RMujGBcbPr{>9q*iE~u7x&96U^xg*zXPe9E`?hy{DMT z>M>Mjn=-K7#`9~lKBQ1UUo5CpYY0L`7ANej zKRxdjhVpx0D&HeDMa?J>JRJmygFOB@j+}F+UlC*&njeHKxa_OZy?t*xv;FwpBFdRJ zGi6H?tcK`Dhz?rKEg--u1epTPUkg);F%{>2KI#rz2vG}8VEIrgN$7t+HvmxG5sgW$ zI9}=H5t$i2Yt_vMGh#P<9xyb7Ryfhfun?6!VHW0Oev<1a-z-_4)q1Iy8DC`jlW&Sf z1;61G?`9NPU?(fl#!!G(UgFnJlLJwT_GyPil+!{oR|-FzVs*(jL0-pWCJ3TE0su}T z&+Fnj=YV2!9{m?rLz#;f8D0S)fz}~ z_mn$UUVJ3*Ks6L}$n>ftX`EVV6~KiUMf#gAr4%{??=-R!fa)A-jQxh5k)p=wXiT(% z{VV2WBOs@Vhw)^y{0=`Uk*BwKaj#kK5L2IMM2i4PdM#xG0unb6PKE+3Tq94%&bM{z z`V{cqSZ7m@DQVOV>oVyrsg%cei3<8p>prL?*&g4uS $^_mM2kJhFtb0rtHX?+5MoVCM_qAQh5`ra_A^1{ zqo>HDTdBK(u>_Vm<>2CrRRvC$WO7}Jhvhx;BFtL%lO|rU2+a%aws~KJwz{8Q5#(+n zIHVN#omb9VIwbg&SN{g7UWfMgKeX56ztZ96L>+VT4!scP>v=MjeR4Ui(Oq}^8G;Kj zEO;@pEtx?8iWxerJ}{Yka=N=d&GW!acrYtC2;UdzIyb=VG{ZLJ+Nd$Njx2ZH4-PYS zcUIndg5OaE8h6E$T@>0V)P%%Dso{>cjAuSXjDB3T$qn(Z9oKn1+n@VwY4UR?K-5T* zEnBvZk0nTvcSpro#j3NVUerzxmN8ymc*P-T=sSD<@L;|_^n(_$xV3&c@iCI5 I*@BC)w`<*#k{>XJ@Wo5Nzt@S?TeeU~qn1I|E zj_c{~H0N5(?`QwIa-YmVl*8)pt~G!MjKqffCUX5x`t)<#N q^oPrZ6wX*P -K-eB=bi`&6^q^JOnM~1oTLL&JP%*BGKtxPAs`>z7l${z zsr?sRI~`NZM|4)VbvE+&$_}${Jjr5~AWZXgVV}0qhk0;Z_Sncdh6Kr)!2tCAgRguB z^C=-O&1ReAH*-sMi$*oSWZU07veY-He0?!deamLd!<}a8n8mbKS&K}W@>#~h!ZYf$ zp>%6v{Rmm?qxr2cp9zHae1`BHsgGK5X~K_Rb_l#-DSu2Q;7!GsPqhLZV)r$Xi!h2h zdf$FE^W;!oypL7l*ck!LnX^4IZT)+f0$n~JZ w57=83qE8g}kHaS#bW=c9xKF6j%HxaTlHWdc zaL=0%h@Kghi ELOR($J sS `Q+jI4^wrkH`q2 Ri}E` zT36N=B9uuf-qtjAn&-9+T*^JgIXA`2GP@rZe3n>K@oS_7TdyBiNM2x4b``R$h{yNM z-PFmw(mlR(Hz2I@ocfY!(s)oGiq?C51RdG3E|h)9INd)tmSrt|*(~6UV6d{(eP1Yh zIacC+CPPJa`JiM^KcnA;og9_G#T2`UcGJu!@~hsRi}4V%7grtxi{^8Ij)15JQ2?Ov zp90DAMr4Ic33IJ^?R>emjx>8KUf`Mi89RG $3 jvg^=LM!xl&y-@7#MBi#MC~>91QvN;MZr--VmS#FbqdACcsG^|!o&P9)AZOf- z?ij^8s!vD68nP%K+b7aq)wQs2D9xNxVNQY?jJ?S^k}fxK{M2`#zeN|AHw6m^4X4z^ zr<0ioA nUC0}KBZE*SZBZu4Sw==>AQemiO)cTC_;5i&U n2{*GLmJ z|Ij?-{5j@%>&ngK%v@*ri0716lU5?Sf)6#aU#)RpRzFmC@(aNE0Q2*9i%1oxh`;1v z)m{4K6T>muH-f>cC0e6%go3@x7Vw0YfMPi$<3yc-N5%c?9LCgOe9q&|eqnW?kZX13 zixN_eKR}gwYr8``CbAZquHyIYwS@13R>l<+`CH__&4$LyJS3QBzGa z=94d1e0!ujd?90fib1?pV@T(EqcMx2hKby1rv)YI(v s}DF9_>6 z( 4PbGwpL8toH5i)0}uDz_oJw;o5Fc=*tBTCUAy$`HM44N0U@U1hx;;@)dkQ z7|%;F!zXnD8Cvlu*HS-Ir|)(C_DWZ46igP^)xaXepwjvZEV8A9ce43bSW5}jB~TxA z0fWf7Hx?4r=f;nG`^t*2Cpf7BCB(x9c%UtDyRKhc59QQ1J!6}kL3VU~*N0Tz0_zM3 z52D|!ywxpaJWs_K_Fn4&Q>~eTr}VlF6z0erc5`oYcAUz0lWdDQwO#&<)Gy10U!CO2 zVn#u^X5gp`1Wg=x!S^9cRrN@ov+HH(T6R^MXndq&`ZzRS`!+I|NP)cw)W@oDd96~c zeA?I27*iuY0^R Q;c{-$rI_J+gnUXR$cOzoS*=QrPJ-F$s$u{ju~_Yq;aKRU*J zV=W+rX_>oQQhbcoJ>l3++rL~Eah9vAtK%MM2ep7qkOOlOeX%r=k#0u2vpVRvrtcm^ zMlGkq$6qTiow-twbhb-qv|+tO_ANmLJKDd;g>mv|^gbNdmZmFg^ho-=btiI0@$*oc zqIZYh*Y4kWlm6|(GOuTzCyg5Od7ygID|NJsKzAQk-rAm;w30(M`-Alg)Ob@9DvFTS zSd;1(1QVP$$%fqLB;m#vU1-!9ZrpSF7FYk3!+e?uN9>n5^rjuQw&f^XyJ}dX12xbmn!qobprE_tRs}G7^zE^SYZh?qeT$Lp+X`(wo1V6T znNpc2CqnoyAvkEmI!Zo~ZaM|=V7DS9K9*xglU;I}Jj4vdeG?&vA$=fcZaaF0M3A`u zS#|)Xe%qPOV$09o2niLFtceqyYN36y$aD%8c^fpGFPRD7e3>*VE#4h#co@SSJjXhD zDt36df&!olZUHCM(8e`P (vMp^BU3mJy*@#s9P7Bc0IsA4N{Bwp z8&B#^yA~s? -z+w}S)**|(m7+ywn1 zG~&bG9_7LVeUWV%0I^Ldm IW%@a1s5mGly$&3v0`emT^1yMX+>$sV z%L0 #ugT-*I>Da zWG+n7YD#uYch06pzWLleixqI9YHbiBsOUD3GQJj|L1t5vtI9r&!zMhj70olYXJj8% z$3yRu;Fnz{Dwr`0^C{2g&Ez*VEJC~I&NJf6crTYxd=YI|a#L?I3~Rf`886Qlpn=W( zoIP(XE$=dU%_zlD=)Ibn! 6%>~r*Sb}~@$^x@Z5@lJ zQ2Xbnp{OgTsl4!aMp3P(W5mD(+VCQPy)jLaLy^l~*TGjUu=!zsP~{N07rf0%0Ez@R ze1XI}=M_*iDFU~0?ry~dom^L7dT9wycW^mt&*gR0@6O!ZCMchl$`9fZy9Y4evCJpX z_T=}@_ehmN3#8vwL+z9Nlb&VF*4^s3+B_F )SDuu#yzJ&qW6oL4hh2$v%RaA2%^ID2-Qu{mMR zUp9RhBG^C+In*ehw*ZSom-R<@UoEz=E*b{BrHbVj)v~3w};Cw|4aWG;5o( zeU0LSJK5;+r##uoo-)cTQ!L}5bl*zO48k1I_mw4fZ=0l3>dNU?tM0taV2ejV;=7SY zov7NOvSx6kKIxfU0g}O@-!Z3tnANh)3nd5HgaDJvswtf-&)L7t0A?1@hmq@n*0>Ke zw}8op86I52LsIxc0PL;Vmbq&E7H3}?#*0VHBQved`;0n!1 cs?u|n^|nmrfw8w`d7^%R{2@=5&slzt9p7c7U-2;rLorn*uyic+Omo0C&0d-l zKP@Fm3}zoX(!=w*w6hE1H7iH)1^nRAWkL*Y%o>}}N(! zs;TM+2)+cm`>vQ_K{5=BY9^~- R#Se1LroP?vBxA_r_{HExYPB139A2y>5G# z&_53gh6)()twei2uBnOg74P0+tJT(&;1Rj5a;TH9KzVX5p?O_JOpL*m{_MigXO1<& zvTksnZO!NT?@*OPkR#2(s*mum)5JFre6Oq=TsJF?oq4z$L5kZ~ZK7~t76adA!=NV{ z2BfmkRSM{Ji6!%^DvuXMb^64HRe>aistsfLX$DdnPwqR<)gkbyC0m3`R0}Q;DwaGL zbc{fC0o#`i%phIb{u*aoW!3DMR@V{^MpSz=$H$(gT1GvvV8WN~Nx(1fw#y0(YSzDR z^3-{d^RWE-Jx=P(mXi%B*p+sJ$n^ejSE9B;t>di*y$YPZjJCK`LfUZ|KSzOJkP13d z)fAcY>9|(pi>CQrnQ`rxlbTC8;+KN8hnywN-t0cIG4R_{Lh#l#xa`Q$X!%Zc@qW=} zfp!*CCO9+#E?kC`VS!{LeD6RVyAl3k$VV(ebo|X^9j8?65k=8E)1OED@E3l79&!Rm z+BX&G-IJobNZmoXUIv3m-GL&zvhpe(yJ%th=ySo}R3A-kyRbI%(_+!V8;(N=5eGbv zOIqyqsWeFS!^a{@51+)d-8}-Rq^xX#kzF6)4CFd{vMKvFSI<;39k$`sLJTwaths+p zUrL0EKe3B8CC^u@v59%s?e#s9Si!Ho3i~={Vpw{~ o+V2|H=6<&9JFb>&gGNI8n zimw3e?hEq4S1;woKL%Co(>47Eevp3}Nw5D}Wa0k 4qmsR?A2G~W~J? X&?u?KgMjdzK_#qM`40cq1uc<}`ToFmpZ99IG8qu&Bt^ zIQv~xLTRwh;p5<_)UsR6ogi5h!Ow!#=M3~KGWGS|ciV*Gm1Q6HZ}CNYY>1$tT %6pMs4! zPZB-Q(*b1KHh|K^JW^5WO)8o42S|2l?K><4O{r=O@X23vc$sbf>1{D|I$wtTnSIR= zh86+)(2l%ODyeGVB{w#Jhfc*@A*2<)ebcF~V4|K?1@ZMa*y2Lg2tmJnZ;#CS)WAKs z`4z@&){ v735i4bX5Q zPnwn}mnZARZ@X>QPX@dV>b?Bz20L8=1mNj1(G34Tl6TXTJ2Q3RgOyfU`yyi@l?eZR zekLG0X1gOdt)dsUQDa?ba(6}LM4X*fW*$ALpyFSrOZqFHnE4o9a8>ctF)0J&?GL$G zN7x@ej6U0Pgia2#@mWHknk(6VL;Fyv!$2 2q1iO{HFT}EAgQEsbScQu@%A(H5! z#$90&y=t1X9UQ1bPWI*Fc?NWW0@HSJAbZQn9 vCwG&0`9AJ>_9zfpxWG`|3p3LbLOtK^Fg!g0=f%wI6 }%60wGsw;FJ5WpTXaDb%JicA VCGp= z@AR@}m0w!iyR#iv(-(mmo(Zy0(1%nc4fF{78oWRoOP<{XNG^D`$|uYe7PtissnJe| z(0r 4o#}X}W_8=HtWpIA%kfB-%U0;?^T~iRs~OUdR=-2wlGVWc8EivlZw`uf>iwFaHJR ziLp7&*=SWhM-PbMS{3HL@5ygB&w4Rl&ZbpGl!)-rF(re*FTG8>QRT2r rmkgbPVl8x=h^F`0i%ncGnCn}PmnshncP1;rSH;2 !#>>w(st}E3^)ph~zy;&}aiYsX+Avve3*7 zdEEsgH)D){JVv?vB5wOe8f1c>ump X=I#4SAaK<&Qey+M(m1y0#72bZ{$D8 z8T|m=-cy{Q?mzB7zMb<$8m;14-7%BJ{L<<7)B4MuJox30&-MR8YXF`?bYJfNbU4WB za%iEHUWhV%#=R@lBd6C5uZ0zXbbnEWrjO73PZgDjy+ZplbFViXC6r?eF5tkeC+4Ig ze6Oxz+H-kq*A*q?nmg56%eJ(p>(ei>R0WUEWwZr-&cW1H*?nBi{MHuVq*ZrKm~_v# z`s*|4){!!R=1c2)xvot&i8mE<(HmuX50;E{gfYRbVn{auk*(UW4rRF#ht~%Fa^ lMbauP7kt znhrA?PpCx|zB8iG$g=M(?)OoQWJWmh5 $Hv=9PxH!AX5+<1~-mPeLX`D8|j_0!K z8%hx690K5Vp vah(7wwfDT~3KZ3EgJy)?^T2UEmDVN~Df#X#?*4-I#g^I>+Y2}bh zAb?Zf2m_FdQdoQ2WAgpH1fGTLX>)z&607>D4_1wAoZ5Dkmv^#VJ71f*nb3m90_SXZ z^xRu*_l^QxA_Ev77`_Jp5WFHihHWST63d?~0zqCsK gKsN*d>TdvZGq9-_s|m0J9;t&=a$B$ky4zm>f)h<9aQ74VgWK@4Pe< z7UD=55Es1bek$`mRRO_tp@a)@jS#YT4WUs#y7d_$l&$SI-^<@roEt!$)IBly(X6P) zU$1vrYcJUo(cXU*rA#=1>)XQbYhqphggz$s)amm#cAsD%4#x<>ID4&zv=Iw+wjX}(FX;Q(vU5A+JNp;rmXc6F zwH%1es0#-WJo9v|yWc9?@Y!}$XKbN>X7y5qdICkJ%vzd&dn1G~k)j_=W7UuSK)mvf zRQi@^tl((GQLx}*JlNJgD`&n#i3Gqa;@gMbe_3|jartDeji1Ab1~md`u?lft`~YF} zTVFJr7v*gmuk(&{+Qe;*yFyEpzDxOCJ0&eBe&qG1Qjz#k8wr94Jwm^%%F;4{Iga)F z&~54B!GaT)L^~H@XJ)cU&05R@C@wN3A#7o5 XNciGHfjZxN49Bb2R&9*;3q7smd{^nEdBdH} z)jQ6rnr3}MV~u8M2?dRJ;m8&nu2FaL8SBP7*;t}UEONn#(~eb2oxUsOrrO=CW%XYF zybTv@=J$mkAR_A|fFh!&i09Kb8}T`NLKZchyCmW&F5JDc%&Ju_baqWvjZd)&P^eD8 zhY`B4U-SuI7Pb=jAs>hi3$@-O73%?qXZK_Vd4h%C>Pl3-u90EC6-OyR>jqA84QiV` z-XJ{g46Z=N2C2AkTJ(Moc88>Y9-q<`uCE=}_8pV9&{`_g>1ClXyyo4ErMXHF+q<(q zOAkH%X_l%%2p}zY00e>QFxuIZ6XWClZ)ReQw_V3|Z12*rYba;G+WTa7lvZr-7(t~C z#wI6)K{w8*To^>?F7%#X>oGJwF^JjSkxH^UYR1A_>=Eh}|COQ(p_+kquBTjIRBT6L z0vmYNcBj5G 2D75I;-!?QSG1;llg^sjW8N>lrJVr3G3YShAYT5U>WrQ3 zsF|*c_UVsEN8yq9k-`F*+rFN11vDK`s?BAW8X&adwHFbSQ3UYZY&1YD+#eFe@eYvZ zyH1p>8X^l2Ok5shezu0#0HLeeV0oLUUO|8NBzr<<_v@x@9dI@PE4 $Gj D?k)>^4_-u?%VLDz77AT&u$W>OhiEM4Gsdqc zw|h$4X3my%gu$E)Fa^4}2-E^9ra=Gz>4hRxN^CA9-0&9}-jZCRyCmTwR4!4$a$oFd z_vgfn>W}sAc xmQVZT8E9ei)OSP zcKjL?W!>e!Y;73tnS6qkXFgoaP+54HoNq~xGRK|!nqo0hRBL7VGMCqbA;$bXqPty6 z_(QN)KVKv5$ZYv+RFF84ij=>Fv`0rZh`+=2g%_`CTVOxushh5Q4k%2F=75{`R%8R!z|w$sOu@+ZQe91IpQ-m{QvoaeT1MY| zwGJ;=pxIh=6zymb0b_-poFq>}xf@1 5>HgKV)D@v!^eEowg z3P5yO%#}YtHw|K;f>32bDb}TR1_owTh0WQP+pO{nI*)$VE&OQWZ2Z}9>C0Qhv(GoV z&h{z1-mz_#VnjHS8o;e!9>B|sSrdHbhS4b rg M)JNYoyHFmc+vgD$S!gC*YSJqxR)>nQ{O0OuSG8%`)ZRCOodGk}7d-|U^ zZMlPFgNB)~v! X#U8QsiJ$Lju1T)sX4O!;c zh^C)HfB^*pPRmt*s1G3~-)i6|nIwg*6mT}5PZl;_S$2)?SaLAFz5@X$0Fc*F@tG2Y zj4b%jJUXGW)}3t~#Uu~g09XtP%uVcvH ?qDg z&Emz@ZFe=~;kFx=Qjw~f^YzFM03s~!icQcNDK-*gq~Mz=a6a;dul2)&Y?iE90QPvy zmhsvlcW=@Q^wMn5Ddc!b5ptESf`X8T?P#14BT!+b=3$#{*ocYG7VR@@J?+Z&_L~hu zPp_oIR6{b2jg8~!j7oK5g&uuN*o<79WkeV}!kYs(F-)=zA6E?TF?d(?_^xlo2L~%8 zLpEh`Uh;JSGV=lXMl$0@0l5uIHRxjr|GZJ+Du3EB!kC%2R5#GGI6g15FejAR&^86l z8FU1`i1#4nLb-^LP=7Zv=NeRDsIvbEH$d%rE6Fn7?%ms&dvZvD8-4R-m${!^p
)ZS1HfmH zOQ0$O^gNk6!ik*j3(V!kZ{AWi`2?V4s06bFRHN=ZSG%<&7kfrIk@+QAvI~dqn5`jUcGQ_Hm-%Npt1)AsA^7G`~VGFc7wh!AB8(EL~i))X(IR|FA| FUM)%(^Bzvm4pn=rY%~6QM(Gs z%basHZ+fO*&O?{4sBTa-@R zhOG*G-$L>`}8=gHq0#6f~ z8tnq)8VN`q;*m^w!qvrfE?2jc3I%Yv3@y5>D0`=Ik9XJEzK^Q)R9K90+!tAabGv zAB$xUA)de$B5o1_a3|+hA6d@a9=M&FZoIDQ(INoP35?zn3~w~PQO7>TUVzs_3pH>M z#_$$|JX}dj5DzK6foj|Z6Byg&_X?hA3Eo%_6liYNnK}2NRuwI2Xx4twm0oA6XLs>H z(DZ+eo@)?==HPz+&k<43y9^pLn`Cok`Zvlzg-IZP&2TgrykB54;1hX_8~jft@XBKT z@l%U3{lknj72mOI(w)yoBItw!5 Ro;Ic~ z=L@dtJw|c!YroaC;fgEN46bgE&NW{s5Dz|dH%pdc=+vvi1U9EJenISLK^Eq=>?-H+ zxWZA~4Cd{`X67}~@(V~b_leXgFUyJwik*TiClrv9MW%aaQopIkM#dM}`I`*29 o-ny@x2h3LyKb;}&RJD+(VctEX#M!|*NbmY)jqNB z;4r=@SbA&9SofA)r50PDr6x#SqOxL(_fd0_s`hDfb Dg zCBs?CoZ!!Kxp7v{zZo^ok;Js3L3%r!co->@sJ{mz!f>WxM0dX%uk}mdNqc6o6KRkK zmQyY6$8$2hJu>E6bwMnlXAI=OjYxo`S%fs><>{l(fVe;b^!ADBVmV3e#W>#Q*AHJ^ zlO22sblZgnxVR)6S4RocYk=0c4)M|Tdt3$dLa)hSCNJZ9RCR?~J;NU#%Nu6>KoY%o z8njOjy06_zsdO_Mj^R$!i9gfbcvSnH+>&M-rC_)*7l;u=BO&ptCau1=?$Hjx2oo-W z*wAyU&Q6r4uSd)Xht9}H%gq~ujH$+ti0WDVzR$nz{NT&Kv9tC6hB1K>f5Ea(iGdM&$1)96SAh44NAT1QkFo<;K_8o1&AaUW?l@Xt)6c+l7Z+K1Tu zL#xBj^~0Z|v19D#ZtQTJUBmc3p`FY#i}9otez41k8Vr^Lnj*-o%tw&@vt*4&KR{90 zWLEI+O91ym^henI8SDy?^aHe{1S6!|5-zDK{Q$v`J4X!2CxewO#L@xc <2^#amF8_!vkX+7~|JW;UFCUL)vs;j00orXUag I zDI`&Q&cEpR?~sK*MVs_b3}UaAVpQi_u5}rshg8@4sXR@JF1&X7E3c`!)mRvM$*ST9 z=q+kj8bGZ4QuhWXQ0Vum2mro=Ukl*}Km4ifp(MrH#FtUCKH9T9g;D0~Y4W*6Z(Oe} zKRPD6$h^ZT3A6&C$gviy`M*rm{9+0sWlU}m*>sNg+Hcb-W!~)9y|WI#RyQ2ZE&@UK zLH(J^S49?cK@z`E%kI<5{%3u_KYnUByj4HI2maSrzaY2RrD=9s(gHbYK;jyv7#z3= z@N)rD3Y3NiUk;40|0K}LE`t9s7`UY4B8f4nNIak*p(Wux{5#u^=^UH!J`0>7{cjyF zl-}&hUxBf~aP-A1S_@Fp{@{?q&Zl~Xasc4I+2_Cc&-wstzCV6q41G0<_6Ml5+W7~_ z753H6^x}UJBT#*b>9A!5w1#q(k#TkEH|AjX`FVzkvab2o+PTyH{`9>bH NuTIYxNe8xZ6@O5JP}p7~o+70IP1J`6Rc|a5$u3-ejyu(%JoEU2MO=`sNt=|Z z1Y4x{qjzepZrqUkb}cw)FDaV%WB_(!E8gbR;0g}afyPi-4I-Sqx9cwE&eTkpKT8bv z#D+?LVT-zHn344z8n;J{xJ8IsMA0I22#z>e3+Rcl2Cmyud6M~Nb*V=cpFQZ8R(c#6 zdPyhfX0G2ce*tigoatQZhTR-9h8bT@aLu0tRMS4!0!SyCPsd|Fd@ira_$G0F8~(yy zD1AZq@b-y>8`o4KtcY1(Y&Nk}*9g^n^5lv2JyAkOduoFs78U)q%ZEwST1z|0>C)XU znWOfOr`4*`6*OJrTILNvRNrQziB5!B92J1FK)YI-;$3m3Z9FCS8xCQ=<+#$07YDT{ zyz-Jesw3#!ljWHBUQg_^TIu|i+FSKMK=a^@)jeGVHK9MZXP)_iAHOo;Vt%Vuwo8e1 zU8-+e7)`)kjpw50&)A>lbu+PH&!+$)PelMH5*Nfx$i;ra`;kyDD~43BE@llufot!R zcrjzBm!0!~jr!q|9Z$w kxCiGSy>aA*RuXD)X#8#T&<~KCZ6u7DXTcy!5`qh_>|MK^WL<9SoK-owqmbk% z!Zi_0dkb3mb!Ag=u|En{w$hA_v@N%7hOw?e1#v40@`pEyD(g)Q<#*fUyMt9bI*-Yv zim