From 57cc3e326d6fd5fe4dc37b3d69e884fbf080c9ec Mon Sep 17 00:00:00 2001 From: omiya0555 Date: Fri, 5 Dec 2025 09:01:25 +0900 Subject: [PATCH] Add Fusic Upstage Document AI Plugin v0.0.1 - Document Parser: Parse documents to Markdown/HTML/Text - Information Extract: Extract structured data with JSON schema - Supports PDF, images, and office documents - Memory caching for performance optimization - Developer: omiya0555 - Organization: Fusic --- Fusic/upstage/README.md | 96 ++++++++++++++++++++++++++++ Fusic/upstage/upstage-0.0.1.difypkg | Bin 0 -> 24384 bytes 2 files changed, 96 insertions(+) create mode 100644 Fusic/upstage/README.md create mode 100644 Fusic/upstage/upstage-0.0.1.difypkg diff --git a/Fusic/upstage/README.md b/Fusic/upstage/README.md new file mode 100644 index 000000000..33734d690 --- /dev/null +++ b/Fusic/upstage/README.md @@ -0,0 +1,96 @@ +# Upstage Document AI Plugin + +Advanced Document AI plugin using Upstage API. Parse documents into text/HTML/Markdown or extract structured data with custom schemas. + +## Plugin Information + +- **Developer:** omiya0555 +- **Organization:** Fusic +- **Version:** 0.0.1 +- **Type:** Tool Plugin +- **Contact:** omiya@fusic.co.jp +- **Repository:** https://github.com/omiya0555/dify-upstage-plugin + +## Features + +### 1. Document Parser +Parse PDFs, images, and office documents into text, HTML, or Markdown format with high accuracy OCR. + +- Multi-format support: PDF, DOCX, XLSX, PPTX, JPEG, PNG, BMP, TIFF, HEIC +- Multiple output formats: Markdown, HTML, Plain Text +- Advanced OCR with chart detection + +### 2. Information Extract +Extract structured data from documents using custom JSON schemas. + +- Custom schema definition +- Structured JSON output +- 90-95% accuracy on complex documents +- Works with any document type + +## Setup Instructions + +1. Get your Upstage API key from [Upstage Console](https://console.upstage.ai/api-keys) +2. Install the plugin in Dify +3. Configure the API key in plugin settings +4. **Configure File Access (Required):** + - For local: `FILES_URL=http://api:5001` + - For production: Set both `FILES_URL` and `INTERNAL_FILES_URL` to `http://localhost:5001` (adjust port as needed) + +## Required APIs and Credentials + +- **API Key:** Upstage API key (required) +- **API Endpoint:** https://api.upstage.ai +- **Supported Models:** + - Document Parse: `document-parse` + - Information Extract: `information-extract` + +## Connection Requirements + +- Network access to `api.upstage.ai` +- HTTPS connection support +- Minimum 5-minute timeout for large documents + +## Configuration Details + +### Document Parser +- **Input:** Document file (PDF, images, office formats) +- **Output Format:** Markdown, HTML, or Plain Text +- **Max File Size:** Determined by Upstage API limits + +### Information Extract +- **Input:** Document file + JSON schema +- **Output:** Structured JSON data +- **Schema Format:** Simple key-value pairs with descriptions + +## Privacy Policy + +This plugin complies with Dify Plugin Privacy Protection Guidelines. See [PRIVACY.md](../../upstage-source-code/PRIVACY.md) for full details. + +### Data Handling +- Files are sent to Upstage API for processing +- Temporary in-memory caching (max 1 hour) +- No permanent storage of user data +- All connections use HTTPS encryption + +## Performance Features + +- Intelligent memory cache system +- MD5-based cache key generation +- Automatic cache expiration (1 hour) +- LRU eviction policy (max 100 items) +- Thread-safe operations + +## Source Code + +Full source code is available in this repository under the `upstage-source-code` directory. + +## Support + +For issues, questions, or support: +- **Email:** omiya@fusic.co.jp +- **Repository:** https://github.com/Fusic-Company/dify-plugin-upstage + +## License + +This plugin is provided as-is. Please refer to the repository for license information. diff --git a/Fusic/upstage/upstage-0.0.1.difypkg b/Fusic/upstage/upstage-0.0.1.difypkg new file mode 100644 index 0000000000000000000000000000000000000000..819881c7e65db3a4d306b239b5d242c56231d294 GIT binary patch literal 24384 zcmeFYb8s!uyDb_UJGN~nJGO1xw(T9;&Wdf@wr%X#$&Ox5{p#LV?^T^sb^pKJ)vIcD zcdfN*_82|BZ;YA>(x70dKu|yX|9^x1IYDn?Y36BZZfEagI;E~#yVWw^b6ShJ*VVU4 zuSPn@F8WtzSid}Yjm>Jbn=%qyG`8rj;5V)0mDbzSu)@Yui=%T&lpZdg9~{99Pj;kbtJdbmm{OXdMwpm z%}GnH9E%q0Z{swL!_FZ}T-`kgON?@8R7~^R0p_s% zO-`?Zi!C^=HyAa1veEF_{A59wNIuj9GIeo4z@1D6fKjO@@MHml+9Sj)USL|_PSV>4 zdXwdZcqn2exyH)>0@qyLF_~r|vud54py%J>s(3z(3L)UovxiD(K6IF*tC+OoqVHOf zb&~;TwB8J%WB)sY!DGY+71$gW1aa>-*ru}`q9+)(L4&!XAc*%Kk2|s-YdmP2$+poQi;i}Ho!DwC{5XwJmDmd(w|Pbe{}4n=Gbz3 zK597BKC8kr4$63QW0K#LrbkX{;yvRDi+{UeR4mT^?mAx<+kTeXe63OG@_^O%{p_?i zpgJpF7T~qQESHn6#hX28=S{l#x{o$KvRU8)>tVHTPqMu2l)G117|_j;>-hZyG|OnP z1Dok&y8x)xbwv3`wzr)rccfk3NYc~d8f4N)+1eZqNr!q#b~>!Pqpo$|#y5#^xL)S` z-sADmKc@5Y?5MpdR-Iad|M29wuQi!MZ)>b?zj&d++o#XDk1=B+=Rv{7F9r7@p2Hq$ zMRW6zsaAaKeI?wKmhq)gl-?p^1!q1XtX&3p%Jz2J(!fs8>Hm}=Q4k%Tn5_>rs!-6MGH@I_` zidVEQ*wOsPX{ASl&?|)0wvY8YmDrryn#tsIus>pd(B0dCcnF0BQ^#Fcr+i(xVWNN^ zT9fNHH~l>r?P(Lqfki!C|JZDu00-sh2yA;Xb1V)c{u(24tE=$c(#-61jNCfBL67?z ztml$<=yV5yQEdY1Xg)G}v??W4)A&m`K~DVK`F%IF2T(C22DqkO<`yKr-QX(D>*elF zA|-?M2b{erExlW2ychcJYN=zZNf=^L?feZ$f665?<%!y8C6HG_t5Ygw2~)*uDm9di z11NpN00Dh}D@a2^vERF7FhBqSb;1JyDg3uO1NUD#V`}F{Z|Y%a>tJIV5+`UKEbuGz z<|{H#Cs7DRdR+AO*IAfU47xEQ@3@)!67Y8Yg`M=b?>spM)g#`?ea{PilF8|Pe95w8 z^6Z+jzj;QcVM zOGFaI4!DB#<>hy3Tt=W5ApAUmYwc475>3Aw9Ksy3~h-EUMAbJzJkk-qoN)+Sr$UdRy$_gWw zc$DqpXELxU9s<863Msk9=wRZ&|Gd(J+al!8`Jd*C%pzuEq+a6|)&4P?trxrcP9c@g zT@!#_{^9_88Zh*NAu{8HVu$ZL~Cn&lR$Rt zvu37Zp*B&&2kKC52IkO5w^c4n7nrjLP6@>Jxp<-`1lWV!{B11lV4zh4dUs|>hAqDt zxZO;U43ck$iTe^k-*%~erT2+Uv6BSo^{}=k1W5+Vf|64~U0vv$2lqA|LHbO=)xLWz zjF^NClvR$QWAv-wDJ1&U${lP%7hoD)Ef<@DyiK@jF?sUq4Dn8wvM&2RQQ`sM98r83 z3XTnJfPfd|L^8Ac9G8=jxfbk6J`o4_Owv&(VG`DK17vxpWEog06)t0l716lX@Na~o zX9yotBw-0!$l4Nd=Th3$;bFFUl2cussU%6DD#{6PkH}zhF0#<7r~DX5fGVWa$^s1K zdJ&UE(eH;{2d23aus5FtU1^vD$I`LE=O;zmx?UI06N@--nF zx#sc`IBIR4a|)lCCyu&=}8Vw<@J6)2I0)2NjW$c1P2NruITdg3T3*RY=;0 zZUgL-^D6+b4k?zZz(Sm$uhuj|oJXgSF{#o0cB3P|&tt9&MRqRF{uq2MqG#uyTtze**o#^!LpL-fD=?4eoBF2 z!iJwxPsAGAI%C<#{YSN{YRAetpgs;q%eA}J+ig#Os5bBm;B?p0XAphFS^Lu0XAJzR%X1&rwz`is6uo1(+crqPLDy zjAXk}R3edjR4xB^6g4XUg?|ADTaio=j$S?YzKF4tUbX-ae`T#gqBzeQ2ThTAa--z9qoEkP++~Bk?3mA{ z(vn>&60!P)uUbOmKR9d5|J=lM9FLGBktoRttVuc9>EOd~h8}5+|y5R@;agr$Pr$&hyI&qYa z@L)J0eKtFIhBl|ydy*b64&$lJo!()dL5U?1ckSP<|?8P_25?Kd8mO5oPFeh^VGi`3BCN$(zYz;>{GK zu**~Gf_Fk0Yw;xGWyW`jBVkv>;Qs;|SmFQbd$g@&+hAB}maW99KN7n!S>JF>y9QPc zagC0^-(Pd-!QOc~;pFpP6t3;ZjEng4`MP{3BI&vkg5*}x(pJ_|3>R*&G?887H5!4# z+68mzS(s6F_KJWfOPC?!3Yx1ea?Qo1TWXtt(SUTCJ)O<{#K`xHU$Myi`n?EMvD@?E z8ToCY)=?SHi<=&5!o#f7AhvnMj#6`whqDgXYTi;R?z6S!fB*Su0#UhbVu21$7N4`g zkHGA5NmJ!r*Tq|m3lWbRJtH2RJQ!dkoPV23qNU2uHB_WeJX0OSXn7$^*F|bDCm4|# zkFc(eVVE+I<9EjR*xo0W5o7G_Sg?yeBS5-IcT4VjsmAO@}dMttx5Rc?y{w#r}OPvUtlLma3t4~(r@mk<%t z&i>9v@D|%O{KHPOmOIJ{s1jYZW!5iZcN5C{HR-7hCu9nOgRnyV04w1U+JPZ*18(t8 z#<<5r75w0B?8Ab1bmvT(axs~pzq=vnPKz!oPF>K+EqQ^pTN+U{Oorq4geua4qt+xl z>$k)%D*AhZ8j|TNvWx_#C0jXF8j`DbVZvB5EIVGd>Nj>b^t)Z{{@%VXi_?==$ab9V zWN}g2QO$R4vV-qX;+)pb0Jf8Yv5;mWjIui4rV_eAISl|m<|ORw)ycoB>Fp=q*}Kn^ zX*bE@Upw|Y@!J|oa<>yA;&%sqm&B)?W^XnkDD+*pvIqNuXOZ-4z2jo6XaojC~eL6Uy45wQ|9 zR6Bh0F#I4R`SkfT>;#LPS*tmC-j1zm9;HtYYRc>g0tu8T{e^+(cxRgFM~3XH1xq)f z(2b4H7FHO+Dr8dqA{MUN`=@04UWzzWXWU1AUKZhS4Dd>69JfXSzEJ{i=vP(SUT%%g zB2zU9fYK$G-2F5%&R8yxR8Ep+Z)-fO`0bYb`)ErN)kVBgF>ZW-JO&lpTv$e6KskS! zh}Nr^z)P9#GFK}h$|`BRRs6jv79%ioE=y_KQQjs&1x_J*GmTAj@|J_W$~BAXoSJ>} zz2p}@1=@KmoU!6kWJ#OjSMxse@v>aP(4Zc3A#=#;!uOJy1J)ip#d* zEe00us)<9H!r~IXM~FHI?S0uVR3cScCujEs$gW32QoAiwSvUJMlSE&FU_j(e$;-+L z>u&`vwe`bH<-Z0vg&0GDl?+)#lDX6S73zjDD_C@>Iwzc5knU!2Onr!I|L)KOZCM%n zjc5;EoZDz&V*SKq3xs)vEwtlIDN>UDSac6DfPcWojR`kDQr-c(`Kx%VM8yxE9x&@PbM+xK$bs^^M} z0dQ>06N*?OqjP(5oGo6gY6$PgPwlDk{4y%FEVZ!A4Zs`ztvVJTKssuZN?IGuJF|e` zi&NKOYkYrKhLtdGVkfm9$ZQ5pAiwbR?LFJe>M6~ZQR{E|70bkk-zI zyB9Cn-@fJ9WY}john&Msm8v*@NvfAV?4M=DcxpCm{8kDsP)W4h-u9A?0LxBXCKgsyVh>YQYUm}#`rgZ^$Joi}t{ zaLov+Q%{uCw+zqVt~O)}?W?D!f|8_~ps?moPZFXkYriRm((|AWw>Ovtm3luiJzff-l!HmBM3icXDvEe`9KU78 zzqYP9d0ER~miA8yfmf2S{bA~%o<+UR^gYNd$kt^=W==G0lnMG7EX$&yl<@WrzlHvV zopsvij)pvNv|hB}*{wbR9_xN~=yo65?#ut7z_O;sAULQlb|wJ{2h_k~pUF^Owh_lB zs6H7KC!|eS82VWaB0ezojG*;}5J@bSp@qx>aXNZzJgg_VsUYgIUSO`0QLRbj!w9}O z<=F{b9#rb;ECNB6Z5kOpie!-cf|4rh9`gQ-xMgYJ0gMx=v~Y54UV(bgz9p;E1%Aa? z{v6wARnz$|Q#ajmN`Gc~F(JAxmA~9Ij_kR>4L9i&^BI+LS&Gpn$}2h+FSH|F#-B7g zSN5OU1MY|k&Cw{8305W4z~t{ADoiQWlv&4GFCOxsUE>pCg~cxYoJl7TUdv#a_{ZWQ zST50m@5hpM#Q?lFCgyuEYt}&>KL`MNx{{kx0bFLFR{UFtE6N&BuFnzlj)za^3**p~ zeKWy@s(esFTL7f+v^>l!*+A-JAo~|#LOsQ>kJ2Kc$UMnYa~7eb2?*RW@)^vHGEf;f zO0YtFg-OK9V1SLVzO!qIbUQI5uQi$KDXp}Ozqu5Pt|8pGHqx;V>Z^ab$-hxT^d<%* zx8P&9cG1-HxpA^?R*NUe7`x_er|o3J$UqZ3K{fOae@cc#F(mz1lshM4RVz6fyUS2 z#%-%iMQ3H217Wz(Ie2AG5=cr_tM)x=91I6>vrLmdRZvc52In4l!TCsS{CHNGod+&C zGvpA$xKc3EzNX&VTi?R~S1Y$iw}HIQ>?+NSwtv>Nwf=|r!Jnl|v}qc&u3r>d`-{J&kTGyN=gi=p=)T4JTUd5kS770 zQ9KMmk*=6)7iZ$;lULmu7$rP;X`v0fYj&CHiiY{f5=m_5qgi?j}0*+0&%&r8q)fQ2t?&T0)^LL%~`^;0h5K!=V`J|CtD znM*d^Z=T;jsaNgQEOw_C7%Cs_)u(%Z+=lIN`5?VTdh}St6c3kV-DXZp1UAty^XWQJDrOH8wVq z%HCXJH-A8SS+e?fR^*^cW`1QgqXyn5WJeF1A4NZTkV|lHg0Re)?ZaH7{WV0t$HNgF1m!d| z9YZ9Ya%~l0C;mYTv4(9(cJB~5^rXib7*30s9rfA6tC&f%*P?kCCkJn7jBzofum$0A zrwfIy%wH#gmUjco*ZO^!x;pdr2)-v~RGUGP{R75?ef&!YgE+IP^}3-1f#qc*jNJTC z60&=JW7i)MB;^8#-=GF#UKLu#GWB@`mJ_#+YTNr`gZvdZJe-0PK z&E}?B3Cz8@)(TO*zt%WhcTbldHdJXaQqQ-o-FRr*X8h!|nS;!W3IxbNGQBx9TTDh1 z)xx`7bk2Vxm~WMdqQ?PiGE?VE&ePd?0{^mC-&P}jTJlwZ%Z6m>;w-eORrZnWX+)ym zwV6~xZ3kYcdqW5oAWV3@9XWL{__8nCmaj9?g_UxP;mUKo`jwZ-@>l7<@ggMR+j>bot~C8t&d<1Rr#uqx!J^olHkTT zJaFg@8RzICkx0ED8OvoE!pqTx6^CV8;-~wUi0puQOu6lggUN|LcVou<4CTK~M~*2` z9?WKdcZgGT3T}_Wp`6<`+v*HJX%F_VoA`HG&Ysd>=oHSH1e~pWj}qk{>5^yxaORzU z-%~%_D~GMpI)1}bNP&BrEALpI)`F-Szw6G9#K`pGBV1etW7&oz6IF@T?HyHWbM5Gs zLj5JAK|G_e7$vhw9ir}pm9xG%c&&)p$Su~#2l{E+8tb1q_4D%b5>qEtf4G=@9}Pc# zs*V11nffh1OP-|Ma>k>wV$!@e+c}j?`GmL~A`W}#zLX75@f zaE~%r?J*H1PA$!;nJYtno$RKLM?jBiJjl)|$ro#&st^xZmm<|H6_B*iJw#_ZzN!}f z;FhnHJzeAr_ph7mez0%z4Hx7F{=AJpy}tXL$8@ik6OiOj4kUgx4TFv(9L@>+Z368$)D$vb*pfOAdXEin;q2|j{*K!p|7xCRf+Z=8_8bJ3o&L_PCST2Lqk2o>@)({M zUKBd6@pbJ70jBhFevkfv&ONsInmKL;>*s(bfMbtqcfU9m~&1<=6kDv}iv{t8eJ+Z0h37U}L%r z1Pr<=ASFPzHTr72*Z(}c9N9KH>w;(Z%B_vYVXMYDRq14LQ)|ie(um-1>2%Ydf~h#w zcFiI5)D(*`02}xi-{1hcz}QYp^hTw)8Eq5Dx>gL9v5rJ{3O=ya@U ziDFVFj*-hwkWe+fL%7KlXCD1Y*t{j<*%{C#iVS-5{I|t>-&t~27D$fro?`Cn;o);2 z5Be9JJnn3a&^d0MR3xWl$V|Gp5PX%A$?3^RArqX8MU->0Vv?T;sqd1K3H3=Bsh4da z5B1e7T)0eloQYgab7_2tk`-ap(F}aK`~j@6RLy7hS3C#0L_sNRl#uD!LgBn-E{>B$ z4zLmH-=xs#V&Q^^VOoRbCtotX*3Yy`zYmm#Yfs#g%O^%QP2}Flj;Y19rDNu*k`5U_ z$J*BxeX1@dag}^{X+e}SnOraPfNTvd?dTmmrD!H* zRVBt{Dx(?3sAOlSl*gv%#u%s-p@1G-P<5CWsflb>yO`Oe~i3JL-l z(&;W-;DMK=7x?-4{~$i;WJk#BXO#SN{P&3eNtu8CuAQZssj~~cr=hKliSn#Hia2V| zjsD$G^ZiKup~3UX0%&<8s$$tv(o+XZed*Vu9%SW*?h~1 zf~<-gci0hwr_! zcYd8`z$8BI%}&nc=XHZP3-Y#=Ui50z`>bxyu^5N$*U&M;*4avyl}-!y+m&0r=Wewb z{rjjXqRw;aq&qJMzXKrL^mZsluVcPt(k(K_K31JTj(xAL@;?^t_y^*!l{w>5Ki z$Eny}>|wsU`Ea{a+?!i(WwtjJhGN!EZN2hybT~&JA@Anxv2@fv^5f=M%+Xp0-lzG? z;{I`GKWcOMS%3IhtN!iE#M$TZ#eMjB!^BwU{z;Yg;hL zfDMMYyJfKxe!mM9v;s~pCK;QO!8h3+$C8Ew3qbFQPST^=!Q)}ukAk{7YD{(n=3_0WBNexY+ zvI}=v?i(aFiD31G z7L@0O5&4StO;%6N&2P`gZ)QtYBGYbbzc+32YuN%9>zUkc&fsJo)lBo@>s4{bLDlk%yRs9 zw?qQ&xRkW;Mz=>d_rvz=hmhwjxP)%vCJ0(FB8auR_%{1q8jR-eNUhH3doSe;E9n}J zo~NB1F#mkG!6C~2Up{*xU9Gd6IuKKH(3bCl+7nIj?&>kpsG=iQW*+(tXLJZTW`q29 z)R90y%u|NW9;p2>oPY15=TDq5v#SV6NC-3sx}cww;mk2^SGaYWrKXjn@Luq+f-dVu z1D~d!6p*j2C?9*q3m^pf$ged;p`R9&rx(aryLz#t}AvV_zSg5J;c%fg( z6Mg%U9c^Hmgu&q%KI3Zb{v`_wN+0jUAk-_my}55z=9(ff{v9t^md$6;@Neb-NlOUc zt8zSWIfw{rhQW_bgU>fO(LFA!@;SW=bUMIzCXMmrufHsMqnTW^JAy1XGw40qR$~a( z2x9P&t4eR&!FdhAsu-L7x)|8*Pf_z99H-NSrv&}rxblBArm+889RHUBM62pMFOFdN zzLd5dx^LciJs|oiFQi(Q(9PzGc0{x!xD8)V5atrElY)UNf zep2F$k1O{InVWKs^|Rb1z3g=Jy=?KCt1k(bltos-070irhJveJFaA-X0g8UL5M+ZZ zB95|P#&3_!rGgMx>39wXU$)M32lgYbu05TluOSvHV`bHEIm|o~v!0lZ!j2Uw2E#o_=K@s2h~lqpK_+tukx+tBl9~?zTBr4D7@9d7^R4{; zHgs!LtJnm-JrU;G&^gS*fY~cUhSr-oQfQIpSCd7H*}2ZcidD|ee8QlK@SvLJ4Iqov z5w;=LC~;7fO>$5q)5X{>ZsXFf-c~eq@hwx3ZWRhk z^|vT*XI=8fc7}L!d>`;QGZXEkQxc_Os2M{g4BdsK6c`IG6_Q@6f|?JGY#Uf1runOa z2M=a8Q?y4))bU!LAH)CRX0eoWo5~MUKYl98|GpqY|KX;SsiBFjDZ_ufV|`OQeO2ZEii^~z zop9QbdS;bf#=|9GBqc9A5Ife3Ojr_VQ$?=0j-5goOUxle;TWSv6pSKIeFKi*UnG^b z(}~2Tbmm1#=f2OrdQNaWY$z*`4NqLP0a0}dfs7{WSsV_n{dG*Q$)=Mq{-n@h0-OqO zVw^FYA~$rbEp#!#8s$*v9GEH*V2%dIpGFAtpnRkGE?~z_7HjwxH^kZuLA8c}pgTIj zop)NFGF4JWxlMMCnvmhkOfdtiXGUc19?IyEZUotY!5bl~pxty_Xli9O<6>8w#6GKb$%^Q4Tpq z(<2UE8yGQi@(i3uNK@A(`eL`oC;O97=uyWQNLkX@v=6Jp%cDrNeEzuo;hV!ysSg(y zNIo5z@=3Lw?CiEa`-f_wuGe|EmHb0z*^SdjXZ zRf=UAPt>$JajP*3Iy={Ih%)J(V=Fh;42UsIA1(t*|D7|_OMK^`^^kfbjDB{;g)6;D z(x7lE!|Eq#(dLpwF9B8+!P2Vsy;yimIb*ziTWJ-{u5rvV<(DOujDSOD7WO5Li+Q3> zE7y~CQntx*Z4V04=Kp76W)?|@xpG1(dO=?VYQ6X;N`e_~s~;1mvW?h&{b8wdAlX(R zmP;HXreO)v;g~q=$O4MS+9dC@4@JscNlBAfG(yAsw4>e((`kq=a}NiuYJvTpG_FWW zM)p%MVSc-R7;NX1>H$E|cc2I|(DO^4uL|}euPt}+2wSBh#gS)hYXB`0+59UYRaB%E zTEk#Z@!9fhv8&&48~#HR&Dwk9&^htb6y&8EMY~(RC8thx>IpP{L8~m^DjJh=(kn zmTC=GgsS)>E}7X{xnc@|&wK5O@wJ1PWG^uqOi9ilO{v>U&D9vm?`oG=yIO5sz5nmh z&)QyozwZ}+U0>gX39`p}za+-CO>{_sfKKwvjgLl9 zPz3)!^tW}ze_YuK*$3O9hi^>~J#7L6DU*Gu#$4k(D-%piN^+6ercFnh8t(DIs0pDQ zPAs*CCB#)hjKN+cV%$UOSeyHDMbd=@tZYf4FgN$OQ2)5mY#_1?dQBXwajHt4Rr%&a z`Pj+CgFp#vZ}EfJMeisNHW;m7^Z%@EP@1!a%69DA)xv*_EXZ!`5s0n~lYC7(A**)%!H+r39?mdxj`Hn`)(_waWBf3|;wXM*V0rtg%JNWp&Vs`~? zb#M}t##8%SyChV02%a;_Yprh#Lyph0(jgI zH43#at?*$Rzp!pRYD3khb`)>t&3o?}t<&iX7|s?n3E~N+=Z| zjzqoZ87UW=jl#>q0{&IE0FFpBx0N|xfVavNjKZ;+H-uEI!7g+o1kWfuVwSk?V`XM| zHZ@3&;MA570n9q3jh7qJRHMMv2ggfe!qIK`a7+t@`r$YNyE6;L-}Y==o9?!DQYhS0 zyx#MZBPkS?hx&yz*+56a!5gSzQNLXQ2H66Ev~0Zw`S?8KH{_?=%ycMYM-v#*C*Jci zgxmF3U!?=`H-0^zgdllL%mojI6e2QVbzA?%A(RIz?-sH5IWe#vBgwuS;CF!K$Fc8QYN=lHi)HWX>e5*e%{5dDal zfBRq=a}KIb(*QD`AOIgZPjHEV@0evYKW}Z_)|n2$1xuqyQRiS3YpDcMur^2!%opjA zr_R@an^L;bgSiiTnCv2r#V^~_;{|ChdqeaS+yKo$^G+Z1QFqHoyN@{^=R_`Z7B}n7 zRhwTF$LQ|gdd2OXOht-Cgztw}D9}5|zu5uw;I!Gx*{p#lSw};~jxt>`UfzY%+}zC} z7Khq2IG(QerZk@J@72=op+nCPmFxtlgA9J}p6`M*kFR@ShPUg$(lj3YF8A8BkJryV zT~E3^&XaxBw11F;H#=Rp@2iwBS?dxcb^QRUd`Sbv{ELB-t~w`p7d#h$Ujvv60AkgRDBnz1{2?~*=}@o;wn=;O4ZWtr*QZqZIg^BX!USgNy4W;rL#jTJ5M z)L&i|`K65Y76~^~nf0n+pYi|Ma>E{2#o=bOC+Hpgrn0+D26+JrXQTrWk@4X%~$X8b`sd`KHOF zxe4Q|J&HkOXHRi)aJ{!&MJw=UvaHxBjOuJpmOXb^7UMHlcMFlmrs3jFC>AX-erTvZ z|4fvPlgJ>Kdb)pb4x%~&X@ zY4I!3$(z>SK*jPp#<@dCpbF|8N9_-j4lWyB{z$f@FZvUYm-QGY|L^T-M2ke@o^ zHr7M`H8eB-HT=1)z=>!{`d6V|AtSMJ>}byKHruaR=EHfvQ?#BUEC zO?uEx!y&2MY_MF3i_w>|%}vd%2K0?$R(k9(>oVL$DxW$`2mrt`T#d z%WZF0&DLt{fwaV7?JfZ~CU@9q^FbL~7|5$NcLE|V1yS|MqCWG@iAz~1Ny1?TmU>(u zT3(C}u#XxKtZ&9IaFmX$G0`cg&Vd;SYt3;M7hmGz=clTNUjT|TaJ3P<+58;-I)snn1?iq?m7(X;JmRSp^DYEA_1om?F`vp~AnYS%{sOT0SnG3-dA%~=y{`~K#ny3fXn zi=6$;wm#IJV9Ij8Kz5`_f>cR-4&z7R>jwftO;_A4obmfj?LuBJ8P}5 zuRS1e%B#f;aKdd9FeDsZ#0k?981BrkHGf4o$(yW~m;iQh2HvxVUlv|APG3IF*KTld zuIyj;L^*>YS#FhM&4F&7OU$Z!$XvL2q2iZXN;GN;-IP(YjUF-SzfU2J@U z@ZRm7bgg+Yb!7lS4S!1U<6>gUgew#`u(bH!BE326eBbxDn>kDMl4i<+-t7!5hM%y@ zpnX#QV5e9nua*q&@`|jVfTLxP0q;9WCHJ_-b#vyET}+xMz)g#*&%dDr(Xiz7l5O3= zNi`ges811kaYUkoi@8aPi_5a2-jg4$`EDJ1i^-OatD=d4|QgpPkbo5j$jcf}n>y(-TO_X4Rm@W-E@|}avclDm zzoz_EUu&_O=cjM*7PZF+A|8?w_jPe#n?CQsfoEkB;KSSaXDvpy@3pHkCe z#^jYE=Lb=x2jRtYu&G2PymWUaxqZU58tHO#a!i9P;d@m#>ge>+aLQrCy#3w{P$%K& zG8XdI58#0IaChc{U;|$$^ZSGOyLJySqq<^!w#jCYZwH^ZeYB!M$&nGQS0tdYqPS)<7Blf=qO106^LuVV(CNV13On zzNhV)1R9gtyAuu})U;W15Am)`Gv=Jv90Dt4QX!-p1Dz%nS43C zXHtnn!64lu?ro44$VL#kSar-V(TSv%>e`-Q2pa5|l2IT2r3LtnF5!rryM^pKRxX@+ z_089kk*4I%*)s=|Xqj3mb&~knXt`=}z>B3voQw1LIiJ~ATFP#z6P{*!ySI9&YmIB- ztdWPl=6Ke%zZCj79A?30g{?nlrV*G67J)SJ^gCWlltDePe!ZNZIWcM?$rxZM>@?xp ziCfR?Pa`yTsv$VQZ#WQTH;{Ps)Ys=ObvdR1@?_53wFNF#n1?bxMsbZneHe~GUyh95SCyD>(xrvVm| z|3Cw4U~GcO$}l*=se_Ty7lirwan}lK`&<}dm}LZ`)==%sH}NCXu0Gkav?z*pQdoDVBi(*&6_g~_=2h7-eLf!S>X)s6g?a2+{Ax1BM}2F zb??~9eX;=b<-;%@tPQx#d)Qa`oOYbH#nTqBh2T8PnykZnar8%&0)JaU#+DH-!86t~pKj`9JrQU5yZtGz5v zT^tk6KCV3~|5*(h3fGD=7E96$r@0TPCl{D@sQS=yP zw3;x?_m$tuR&$#hXX{+9QwsGpaR!Mi!|>2$p1 zJb>$Drm^%00Q23^s&AYl+ybvT`p41?LA)5v3!LU81N#!}~JY_554k4H1IJ-w&yt@egbTUUSrYC(8KjeXYhdW*tE53$pfQ6B+JfS%D|1@&dQBkhlmsX@fK#-P_ zl#&KPa_Ei$RJvOjLPDfe2I+1Xxjrs1P9&mVziWWT*zCk)}Kk}OW6H;$OMBF z%qKf*-UF@;IlczWZgM>>?ewwT0QpLOz?c$Qv5^0<*HY{Zn;Kv7Qco%HO4}Ap z)Zd?a`e6Bsg2&M#K?#Br%o0+3?9#F)+Z+2M-$h%GL`wt;^e7!3Q&W}h&T1hG=O)&+#a8qkH@h(Al_&y`QV?Rt{i8knxY+eQt!^7b=J>= zW91A@@B59aSAQ0W% z@y%5%8*O|(yH?~?I{g#TYq8-?GRsU$Yg-mn19^t)t3Kq_B)^p)qAP)x|}gIH45I!^PI6_|OXVEv)SQ zOk|P0_}EE8mShZ5-%qv143j2#;m+~c5ox-Y5@@jetGCTdT4#JdYJ5lF*GIhcHtO0< z@1=q0hr3ERU~|XRmkkjoiYbCF=xV!CF2=S&@PRAq^(hTf4aY-?0nOWwm$oRg&x12b zD@=M>)ecBDyWJkS^1J8TJ;Qgk*Rz&H(`gVmY4A3_ipO#y3DOX@t)@th$4^8^`c~%} zwyNa9>b8m>b)-{}C-J;sV(9rPd+lLVBH&O}mHlA@ll=992Q{Dq8tQf3!#UPdO^>|CFQNo)U+v_gX)0Czw5d4mL&}0>M0-j`at8 z-H-|VI%<@v&cD`3Ijhy=PWF8hi-i>%#x#haY`&##zd*tbV17yI^}wwuExg7`y;f9J zcPj=)L=qMxsCJl;#J74b&s82G%>X=PgOd=*drfoTOI^w%uNC%yEF`?t?m`~rM`#2a z94^5B!TT)R;EI4*yH51#NqD%Dw$W@p)dFI2TaRCeeVFcWI?sa8!rma(!Z@#FqECpk zSf5^3x#JEaYEFX(V4x}(>i=>G}!%{8KOn0#f9)?lyE*T*;TSm7k2lOCfWsrAiSBWurWGpx{ z%&H{F1$7YsbB0wCFz^dEJ;(VguX8{DR6P*T)di5(sSV2Evu3hddzjnMepgpBk@i^> z#4k+e7NVBfR^#vUG|f#?E6d`;QoZ2ZKLxyxRI3fOEF|B&g1~QOZ3FxjB4_Ei$;`x@ zxh8bGbvAR>Qq0?1NI9}eS?Xjf#*XKhEjAn%<*JJ-8yqAv&rYCMQ~70X+|UBD&1o5K zf-qn%)MpI3Wi<*8>Yd-Ge~`yY3$%b9k$2W``#WDT#hNzw*Btk>cByu_N~4bdSV2%6 z1Nwb_rka81dy@K?66_S<3#Dvz3iU?c%c;qtUACuP<{+TD8w1oB!)vs z3h5w0_~<@e;vnf$NxhN3;VPbZYC1?;4t~h-qf{jfZ#CzYAp4ipN3|2_kt>m37C3vb zy&|2gvRVbXM6{-n~7$4mRv)UB4NhD_m^Q-oq? zk4`f0UcI3WGVWh${8x^i=MFZ4NypAMp0F9fWZjkgWg_U!#?VfN#2-Evp5~9n8?8CcsWyv)k^?BH0TSUcZeI+!`F_bf`ThLK}3{#ASMvS5nA=w~dqH1l` zFFv1`=^ye{r!fRP>|xRv%9~(8)KdolPmpQMjUy6ypS$H$PJhQLTr&HqV}9Wr)E0Ym z)z~Alqw8kj5;$`x@~pdRy1%wBo-nfv_b{}Qm`6vkmt%0nAn3<16`nCNGGVka zKs($Cu_jEs6hUn&r@}17v2zpU>!?g6NMvr7`9L}}Jy7VSANej43qv{{aYCcv>>6Sr zt8}P*;8a2*+!O)c2K#k4RhfB}&@bJ-V^hn;*Jq|><&lci#|dEn10nVc%F{^J4()C1 z?XP{@gE8~MJ9^Sz!B;r>E1)UzVNwC4hdT(?F~3|uv#ir(6nMs@6d7YO-_qG2_eSx=%;tUSf%mE_R=2o@|bac(rN$z5-a!M$LH=q!; zShJO{3+Ss47%6{A!m;--f;Z3m{9>Oo>jKWE3qYa93Oc_j%MBD#d&M=_0JIacg5;vI z$vOwsQ9G&L3Oe>}iQBaWV&JxyaVceIoS}zQnC(D%m&*CG0J>7m0@@aQcQ9!3kvhyC zrCshx%c9(;x@D&dmCUM$PWPiA3R^-}(eur?(g0ecYm5W$tKB=1UAz#Y$V z&RGGF;Hon!4cnp&P48Czn$7%cLdg)UP4ZJ4#H5`*QRucnPMx%sy8PM5`f!m`eRXN9 z5rOOWk8w)%6sM%;c=~h&$EJj+f(rWR`v~bJGhM|R3XY-_B>5acJ^BC^skj!VPz`Oy zI`88yjx0bfFwp=OFXd0o5c74v&AG6$KzxwL*-wgIOJqobUaJpf_6+&5$xDW{FM{M$ zhFydA$TX(hb&yXVdH)FNj=WDWvEM0IAXEztG=#9xY4?kfkf`rM3VBS{wX4nX1I`hD z3YiT_c<|}EtZ0xj29hBl(hehal3R|Tad z6Sc*5Ioagt{o0#H6(Pdl=bSVI%LR9uw9{&T!}Kd081?bC;8hQQ5VBeByC{|0^oazRb3dSqUctBRQwK>^YK^o|qVJ zIYdi}|e5xkDp49eL$YQHVe;Cq?~&yNBu3}W)-VzWu+uPb&kySt%&;E|`p zLy9!?p^XWOCuA`CiZPU9mGuX$xtE{X6n`q%V1=MwE4;M)Xk|K2bQ!#H_Ox<)MB&ht zXE>I4eXwaMt>MHVOR6K7oyLem7g=nN|3sP_%gNePRdl4ef~Ii)%p`5;hx@F`x3>wo z?K3qY_|w9&aKkFvZjDWODB;Jv^wKOXJ!e{(h6YDXU*@GsF{VZgbuRVb9n6WcII47I zpLM#sYd#JGo>?E0P7O9^S}n(|I9rON^;^G(eOM2R=fWq8CD*699!A>LdrxsHTD6k- z9wFddayZ5F^gojzfC)F?&m#i9vp`wsh`h zfzDbO%`T1(I}8+*R$z zT(BRr0O#c^tMe(|fCCKKNtVa~2QmwpKI?kXivdUBKZeRI3XVQQ4`oDg^}`@S_sZ`Y z-lbYf%mFp7ZZk5K173!`Z3!8v%J@$S)#u`o&wpb zw<74{nga3Z#7E*3+67;0l!D_qqZ+Amcs!?5akNwi2B)EeQWkCnm+)` zQ|O`ROg)cv=U4-#KKA^VawM@z7X}gP=XisFXl3fE*Dpq1{X8Wb!Zv;4m$%RS+C=jz zDL_;c-Y;;pF+8p834sq7TI#Te`6NGEVJ3}l~mp$p$eIz=1KVM>vM=P!QzV?6zRj$c}5vgGoh&A#H5 zo{-^DNb!89fUFQ%QqSuu0XD4;jB%-wHa4T74j;Szu5&7<)2|6087Ea~DtY+cDw50@ z#4l$`P(+Bs9T8U-@_#@=Rx3Uo%f}8)5!AC@j5P~?wXBYghdqHVfS?PG96G?tlLOC^ zI8z~WE=RF<0Yc6PC`vU-D(dVBlMkL2I*%w_*dg@45Nna{P6gL=eqgMPvMY5QEgk{_ zMo4R#ZQveA5-hvQt)0*8hFy~APb<4P+N`jPk$Hhr!0 zENyB_MOVD}zV#7-cGFNbv3gznn}ka;rm~U8o$NZFr+_Ulzn#LC&OayJqdtLb)?vEJ65<%Zp! zgd{Yfcq!l^vvaswppxXPNe4MFBE=(^i_9~v*CAQ%kt4$6`SP)$h91kxZqgH%M|{W! zQ*zkHFs^U&zrGq-Bh%7Z3M)<=VkU3OBS72)QIuC9cH9A|0=?(nQl6gYK1xZg9=1yf z=?{W0^0I{1W039eGDxPjejYBsL{8O0O2FgEE+)7FBN8gp`-7L!;AW;9I zBD^1TSE_WY-usQ>e+Avq^4$-;s}8xq5XAS|b`yBtBCcMva_w@eH&oE!`{|^YpJ|F-V#Ft^#vZxE^f aCB?t*1NmmBfP=%m`Fy$Ao|3e0ul^5jY9wv| literal 0 HcmV?d00001