commit 6a4c7fa4c68e6b8daf477b96940fbe0c1f8cb90d Author: Adi Date: Mon Nov 2 11:13:19 2026 +0700 1 diff --git a/lab_rag/Cuplikan layar 2026-11-02 105636.png b/lab_rag/Cuplikan layar 2026-11-02 105636.png new file mode 100644 index 0000000..cb8be3e Binary files /dev/null and b/lab_rag/Cuplikan layar 2026-11-02 105636.png differ diff --git a/lab_rag/Cuplikan layar 2026-11-02 105655.png b/lab_rag/Cuplikan layar 2026-11-02 105655.png new file mode 100644 index 0000000..267e8e5 Binary files /dev/null and b/lab_rag/Cuplikan layar 2026-11-02 105655.png differ diff --git a/lab_rag/Cuplikan layar 2026-11-02 110319.png b/lab_rag/Cuplikan layar 2026-11-02 110319.png new file mode 100644 index 0000000..0a65c99 Binary files /dev/null and b/lab_rag/Cuplikan layar 2026-11-02 110319.png differ diff --git a/lab_rag/Cuplikan layar 2026-11-02 110335.png b/lab_rag/Cuplikan layar 2026-11-02 110335.png new file mode 100644 index 0000000..88f23d2 Binary files /dev/null and b/lab_rag/Cuplikan layar 2026-11-02 110335.png differ diff --git a/lab_rag/Cuplikan layar 2026-11-02 110347.png b/lab_rag/Cuplikan layar 2026-11-02 110347.png new file mode 100644 index 0000000..b5fc32c Binary files /dev/null and b/lab_rag/Cuplikan layar 2026-11-02 110347.png differ diff --git a/lab_rag/Cuplikan layar 2026-11-02 110532.png b/lab_rag/Cuplikan layar 2026-11-02 110532.png new file mode 100644 index 0000000..48206f1 Binary files /dev/null and b/lab_rag/Cuplikan layar 2026-11-02 110532.png differ diff --git a/lab_rag/Cuplikan layar 2026-11-02 110545.png b/lab_rag/Cuplikan layar 2026-11-02 110545.png new file mode 100644 index 0000000..03cbcad Binary files /dev/null and b/lab_rag/Cuplikan layar 2026-11-02 110545.png differ diff --git a/lab_rag/Lab1_Eksperimen_Chunking.pdf b/lab_rag/Lab1_Eksperimen_Chunking.pdf new file mode 100644 index 0000000..e7fbd63 --- /dev/null +++ b/lab_rag/Lab1_Eksperimen_Chunking.pdf @@ -0,0 +1,175 @@ +%PDF-1.4 +%東京 ReportLab Generated PDF document (opensource) +1 0 obj +<< +/F1 2 0 R /F2 3 0 R /F3 4 0 R +>> +endobj +2 0 obj +<< +/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font +>> +endobj +3 0 obj +<< +/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font +>> +endobj +4 0 obj +<< +/BaseFont /Courier /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font +>> +endobj +5 0 obj +<< +/Contents 14 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 13 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +6 0 obj +<< +/Contents 15 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 13 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +7 0 obj +<< +/Contents 16 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 13 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +8 0 obj +<< +/Contents 17 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 13 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +9 0 obj +<< +/Contents 18 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 13 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +10 0 obj +<< +/Contents 19 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 13 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +11 0 obj +<< +/PageMode /UseNone /Pages 13 0 R /Type /Catalog +>> +endobj +12 0 obj +<< +/Author (\(anonymous\)) /CreationDate (D:20261102015314+00'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20261102015314+00'00') /Producer (ReportLab PDF Library - \(opensource\)) + /Subject (\(unspecified\)) /Title (Lab 1 - Eksperimen Chunking) /Trapped /False +>> +endobj +13 0 obj +<< +/Count 6 /Kids [ 5 0 R 6 0 R 7 0 R 8 0 R 9 0 R 10 0 R ] /Type /Pages +>> +endobj +14 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2454 +>> +stream +Gau`V=`<%S&:Vs/(gp4Vfd;ZV>:K7hh:Ct:>9Ie=2Zj5#1H)#G?6.9+k`=UE-.290#tio?i)ntn1]1iEo8,4+"95=r5E>hO:>fk\JXS:'")8Jg-L]pdjQrMFWlLGH!HG/`iYXLk.I;P^90%Q(dS8%8B&NJm;*o\'@1pKA/W3`T&tnDA\VJ;q;VXcA<)7O/iWa![_/h_j63B%U]+*<(/)L>"MS'js5Qb_nBhJ9$6&F^X2YKo^0RD&W3;*tkLY7E[,3B40\LNb=,g4npbM=ViU>n.76,TRK-l??X<[,84_RHn8)T6jdTX+-R#^LaB6:>G%P9k\6Ia;*]"K%s=ibfDEnVjC8*:A\pR0hNIo6%@/So7]7,HbS]L=M-\Y>M^:W$78D11Vo."?u="`o[\I?]AKFVT(_fAAa?lcGOJ=Yt'dmrGEkH4j[/!NlE:&n/X*3KodWd_a^>bZh/%UQ3=H:n5:0'jPUjZKIg\CNmOKgEst05YtRP.kC1Cde'[gc\qe*k5ci,dB=B>)>Gj4!F2#.QnL#+1;Rp)o)D(B6g0&m8JO[,Vc1$SQWSlZ9FEpe90f2`Q]\s/m=Y>s15Ma!*H?k1rbIP+sJZrXVmcc))fE/P>$:p[B7#[>u9F58:.]d/5H-TFo?7Qh*fc)!+NB$#$UF0[n!VaQ2c'Gu,7:h.X39:aT2M$h5fTHOHf85GL5T`Y2Y_02clbI6/li@cNM?5Vp,t)r$U'i"tC^6(.$nNA4nt`X>*UslWk78b8OWL6]jAPr3%>"n,8I:c=C#DArZT4Y[f-/rIeaQ8P=ZTn%Qk];)HjNO/#)Q0=ic502&f$g*&=Ii78SDb,q\(VTt)VIU:_3Umg9B]1UDju<%\D%TB*7uj1*XJ'GWPdf5Z4@RQb5s5=OG_.@B9>rS*=Ea`__tcR@Q=l%_XhuBi6rmfe2&+nGs3:1?Yu"hM.I)rBXH__8E)3s1X+K&j01#]ij==g#7OMi>L/>NI>=HlP=4Q^Rkpjl&)4/s=*[*f7.=@P(qSDQBeu3ql2aC$\?9_ibIZ46)B..#h.'U!*A?_ZQ)j1nF]8!1cQH2d0!DYIO/L.6K+usVbGVf72Y-)=DRrX@8d7(K8V!JQp,dR2oApFDu*/^<=4!\W!@5G".[,O7$PG82\18n^.iXIYnP)4kXBH9b=-kWLp<0l3ncbp/JVZI5UlBpNF<^KZH"^+UD-ERdDmm]^NR*UYqm\`r$l/l*VAThP:c:gq6mtt3_f"!($Laq/Dr%OI;[bCp8n2j@;rc)DY_okQu"W(!g;XXdj^[X-i)rt@.f9,)<`K?Z8@^&7@TX^tEr!S=\jnr!#LOV%Zi=h0i=GuKrWb$MT.mIo8gC8u-#QE)uhm:NIf&eXI>,S,6Lpd_0>/^,.HapKk6>SWI's#AVgE;',O&V1ligeS/3Bj^IB0BRZfs6p[e,Z,7]%o&:G0g]s5frZ*d2MJO(]=UT6]F8h%i4VU,Q/9dCT)`7m%I[Bp'^(MZE52<4H)ArLup&ugn,3/g856IK=MlEp3fi;a#-=+(K1o2h0$d>Fk7cGe6Pcq8A3HdM@A&p>,,fbV3b`%^LF\Js:i?)n";II6#,;!Ga6IpNEk,h4/U>g-nanq7a2:0irY=jbl,YfT[;8h0pn?cT<"cPfd1.4r`4Gdekb@e;:S;"I[=`$pebiHBNbfR\#e:#7h`Nf4^?Y,e)&Q8Hhp.RKT6%$):;CeTEDQn[-*!T/_[g-:,Ru='<1e)=s";^Q%RB*(aMZC0*R_.Q7r!4>?PUX('pPcaqiY9gm2*I1=,+WGItQ$>ci~>endstream +endobj +15 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2106 +>> +stream +Gb"/'?#SIU'Re<2\A0d@*?7e:^Z7R1h:ca[K4V%VeecJ$k/a$YHbp8Pdr.DiWVBKO:g4L&4$#LXBiKdHs`CjTUe$4^KI$]NQX=NIiR8,$L=Tr4=@F.4U2sdJAaO5OioHiLjW,+q>BhGSSU]?3^#O@Kd!tIQZ6QZIYl93glNH/WN/5Ie146B%HVf/l-1!fP$H)l/N0)BdMYoioJU*93G[JH7g_I7AoF.?6+(8M:mBQ;3H(l1-2WB46?N28/@uP`6jbkpa3KMkn1W+!Q-!:hG>a^#9Yi-D+7$qc`(nqi!^K_E"m=jQr[5.N'4)',o8pKm).@^/589nmPJ#k.rXq>*cOP>%k[8rm!3&kodf%Fl%^)eb(7dLPF?+Rr+$PgJZ!u'W@0auNiTi\JdN3oH]0HEbC$5[]l+LYXY#^'b2T\PQj(lsR-tM7RKq#sAC)N0^>-i'02OT^*'R<#>>sMf'.m]iu/9\^_8NXX+^c#jC%ujOO>F:ZY9H@O!5D\K2'CW7a@))b(pa2een.IS4T&?*u#9S7\1h[M(,e#$A:5Cfi,gKOM8sWtl4+@f$V,SH"e80N_DcV@rWnar5M\OGbOXd(Ih8^0Gu:s$k**R#o]N$r>kB%)3K&YJjp6cGOA#qL![DIpETarlpF1[F%L0UkV:_I6LH*'\S+ENr-u:iSVskF5I.NBaIsIiVqTBrKqBSMTgb)sKFB\d%Af]U,O$3p8N6/t7kpeX?>ilL.*4#5!$,f5gc-0KONDrHkGh=uI;!L^r'X[3=:t]Ra`V0@O@HeWTIN8!#0EC$j:n>eff!S3a\mT%SeLm_Z9odn%qu2Cop\b:Xnr%FUH<([D`^Q/f7<[p(JJ@1u0l4$=9PjJ]*g)AopB4^-u7)MH@XRXP0_]%jg\;h-E?/V"Xr@`)?<\n)>)4skC7$LLS7pQ?D@Va-1a_3]hBSo746PGkSU8^_+i9-B#$lO#f/N/kfcbD0BB=e/j12Gnd#l./cl;<37Q.m(M)Dl0e7uhM`2^JZc7]Q9=fo/8XS\HLHA#h\Nu(9@k?_NoK,.q-M`O248rkC\W"+C\TGc7%^.0_i-cMpqEJ'b3;:nF)2U[6Y%8iiQ8d"EAa]Bfu8XkbD"`-UA-%lA)oSA&`];>oX,endstream +endobj +16 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2371 +>> +stream +Gb"/'>Ar"\'RnB33)W`_Wf:/.mlZ_O.tU`^/F7B;LciA+N;jsq9no]uBH?PZY=RRY?dnR(i;Gk_S/kr>l=F$#D'cSa(X7b?1]:C-J[bKJ?p%h[f)G&+pAWg6EQ2745Y^fJqKAhJMkRVMM\L?'um:*h=R[f,+q_,VeP=lqGID"O$Ac#t;R1d&o&9?cR_8@QWod+eILA>lK2uJ(oc-:lD>BCI2+[;`SQ;VfH'@&LiZgjCq=HpVo"-[WS3L`.0P8.VFbDt>C'nss[^qYQpku"@>`lG1\dpr5H#\T$F+Thu]$='D3*VIoN''mZr<4?^03kfW8Ml,DZ:`Grhobin@&%a]iXb+N9[WAs;mc`j.Cgl1n&^PSu)3dsDHt%:j4XAHkSTBp],"Ep*JY+!1CVt\tXKEIoe-rt\h[/Sp5ufcl0557Q[M'J5:2R*)/N:Zbjf%aa1Q'+[%gdW*R"Eaek`Uq.<>ElK]PE_9=0;e4)%)qY*KX`KnVgs)os.5]_T"`_Oi*>4]9C]W6aUh^H/fZ[7Yo$do;(Jkb"u!OjTKu<#_?8`:oYCB=5/`]6H@(TE/^L6k.-CaQ5['PGStY9El2g>"#00,^%m6G'X?.`IjJ2TPO=*3hfBVo,&E?c\Tip9D[3GnY$?q@<,>FKQme@&1&[ruVk7Di0NKubVH+lJ^UHY&c]XYq.fa0t=ZI)t+<._c?e)282f>03);HM$O>l+6kE)B704p6Zsk5t;Xmd5+5MjiB)-&E15VR[anaZ84FI307Ji66l(JDn3h(EG]7!$\q@,[/p6-ZS8$gnDGWMGpQ\=6P]b!CD+(kBu*!_\rAc("-\;Tf903nL2CUkifdM)Ir\tZZo`%\dSFHJ76j]d:_J:CE228*sZQRaEV9CtA$Aa!Y*k3<=>f]">[L9&(,1!-;imV?>Kd%;o(>qj"gpOZ=o._Q&50\rmB-"AH>Ap0q+d#;@LRs20u4QHhb@O8)]rP9oYEY0X`7Y*V,Y8ZR7+($a;%APbV;ug62i9]-(#tk<.GBN,G6N44ZQmd/m?=Qe1r$Brl;ubIR)q\HlE[$UXiX=!pu/sUI;E2Vs,Uc8%%WVPE5f\kJ^;BEYP)/p#XU&[glRZ).h.b.d7AX=KN$URp3NPC$j-)VTY9j%$sbBR0WeXHe2!>0cQ:[\a"e2endstream +endobj +17 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 774 +>> +stream +GarVMbAQ&g&A7ljp/8[T;H^@Y7nRY&=p.8)$)"%H.uTO';3+=[Mu8!YUb!lZ&3-JrgmQjKV$4j5'E8$2-2O4^k,0?,V>Q%c52&s7RssG!5H?f-\j.#Ok4:!X7oIRd]9II_&ucG,\$UTpbq4.H^S1R!q,[gq%&-DC@2g5mD2(cjMZB23+MtAo^W4Ab*#tp/*XD(-iVH-S^$3-94G+WQiK5(3NDUu\eB4qW*G[.Wn:[`@/K8HX%^mV"L"$\tnt\*:;VTUMFK030cuInAQ)!Jm7.TGaF/`RGNGN)pON2M\,A#gb$YSk.0bDbC_1rDYL_l`?-:,qnk:D8eDsp'XVf6+/>g]^[[[TEXP..H7roc!1*+^3DUqaE=1iUQU`@.)bi/ts]rMZ6O_59PZ!?1\A]]OP1\:gAD(0i;)$9@WIB3R*.[T9`O]$PlH4K`Jf??rD5E'K6sPG*.jfrQM!R%a\k"=\C?@p^!u,EI:oWk0s[50DUa+\n_M"<8^V'A#_L86[t>]X;)3m>f6r#CL9"?\"cEa0eHO(HkJX>+#UL[9phWU(]e6?#g8,"V\Q.M7JlMn=5$,(sYuIX8i;84D\3@OAh4N3f\i'ZI?o@M50+)2I\;/R9LDVlDZ+pXXEPrc"8+1mSSl`;q%r-rJ$3~>endstream +endobj +18 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1767 +>> +stream +Gat%#CJW\U'`HlqERtqgdfq`h"@BJ07@-CmO]&UsqZTL@34?rekPDFh+o_A1)*\`qVU?e8ETY!\SGS[>V\.dsr7lrn?WZl6Tp'B@as6ja4/LJjk,W_+]W3:k+h5nEWc`/@dP&mfl@,WA_Eb<;)s7mZ\2^,-M6?(V?)L[nlCTV8+cC"rT[b9h4pZ@^+]*#tAnYfn`e@1Nj)YZ)0)uRCOVG;'Ns)Nqp^COG!"DaKr-b-&uWuRjAR%9(P;me0;#HhX+"7^8\n2Qm%LPhpqFD0s0/Z??f-:$h[H!%%Oj`D%BI_&hc?-u.u?'Rn^akW?N-JDm!ioK!@K@3BD`VN8U-da7Ae%k_q>=@XO3TVfAYGh5rs_QT1r>mVq%_IUNI=^#`,RqdiW4C<>>#`sWTL@UR=f3`N(jijljoD&8mUcpA_D0dZp>'J/,=.Z.;6RP6&XCBcUdk7KXR@F6&)gTV8DJ_ANUOGbJ_u_fMP<>Zpco]FTs4_("[u@$;QWHo,gPi&.=5NTj`%7?*`b-\8mF^jMh(?3*6WWgE%17D4Z4d$Q[A4PBc(:F\mW8YUM!&>iM4P`^ZB0Hogr3$61uh(MVe60N4INf/5LNmJk5-B\Or&+a!fBY)AH\]e\:I4oee'`:-9^hqsDR+OPEWm!;JH:;V^B3GUu\e2-d,dKDR1#d]c%fT=[)[1#f8`a'.#[:SLu;95ae5_kLAX/I_a`?KR[#!mp9ras=U^pZ*S;&di\g!Wo]VnG?=iU"nLfjK'dO,>^MI^P8mc`W$r,DN4VK'SbO9d=`X>:l4#Jmf0n)(J_DB\5e9Cmhq=#_G!eh/[PC%/g7hR55*@3o*A*R?rmaNnSr-:&@]^<[em!kV.GY!?+m_/A_B_AT.8BPJ(U/=u[2aQ+QmQ=mla*YN[:fHV/_$I$)fcqB.C$k2>o'Oi8#m@]F;Llh*P"(IDA55'iZ#T%sBCX:JiIhu0YneH]N2GqK>;J]hTm=k5uX%_h-9XbpC[.5/lNQXW"!?L-A>lm7tZ6cYh`-$h/BmaBme\qqjJm$-U]54n8-h"gmZ~>endstream +endobj +19 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2495 +>> +stream +Gau0DgN)%<&q/A5F'W.(/6%=r@C8IM3onjC&1BL+'IBKTr:.s0f1PdL0#.=(n"H,(ROT!i5qJcb[2]",`9J5mR8Ht#&8Khhgd>^/m6*rnb*bn>F-#h^".eD+mR4\p`0s0'"`!Rs$u*S.`KOCcKlI";mM124gS_0%=mTR(-=SWbbV/8#mX;dZq0]Db;5U#q7,4]Q&;A=9);s:^gS``KGR-o40`#>X;FVgG=ffe+i6U$46qEoF_N.cC*f*Y0CSTdMrR-aH*NWi'-%_*5r$X"WGX]b<@m4g&"i+*#N9Tinp/eYf]Ks7tQsQb2R1k@&]8g[tRor"DFckf7iWE]TKiQLb`N$39%0da;A\Po$j&a?EVt7X]=HO0.i9pUu^0YWOScY671\s.[<'()U%Zf"$C^l*EPPcEroa20iVf2"bA)m`g8(&nYio`:eQlDoqEa"J&IR2@"0/p8Ob:^,KibO4FZGB$]-liMAG+WtR@MS-oB*0_HTRb4T#!'M]FbYn?PiBUYT*K=Ni^McG<*i[WQ7^IF,#$j*/.)+Y[_D"G!)0dG%7IoJ_o<"^:c5=p*BP5okYf_Qgi=kL\_mln'@mfNo@-1,c"l9sA'*2(-#\.!!MF-A]Dc7q([#DCU-N,K91of=AbH.f!##lmupfT"CC8j$NJCl:F>9$@%Ou4*/VqX/OZSQj-1#8;jMa/(MKdWOsO:\U("A%N$aWqh)%<28>e6SuKZt_nIQ5I#R*jE_6=0+B?Y+LW2*m9h!U^06.j$!Zcf-5YVQ"o5Z@%O#=,R;42_Qn"[Cs1qo4uKsR\AtqXOQ4P1.)(2+"cL0?)=MBE3=E(fW&A\:?/>a/Z'Q%jm@NKlM!WWH2DD2fP?4I0:k.Y#T;((@6GMb':iBXiZI9$??g$p_s(iefIPC21fNI2G'2PW2H98?5E8T0jVfST98a,n&>eX/&+7m=AFVjk=Mm5H+(/^6lQW/2]o_h3J!2]QP[NK_+F,o5..a*DPfV<,ulRU0(Jrp?DG>%Hb)\iEFN$OM_A2Q>h:^EtK!?p!?69k[AiO.['IimU_\UQo&*U0(r9K"VH:]+;ZLZO3a`ZJo5/`ld1!A:QK3g_r5WmM?l!F,_E'jqS_sIK&."B4!Lf[5\E%!E8ZN-ZVSW^3ePBBogCJQ6cpRAhjJa>GdKV[?4?t'j6pcmoJ!Ji).PN8S'B<4s-Tk,_=+mX"=CZC;ZQjt#KZ81SL+@$lC3N^C(ZrV/+WGBHVTNNWmIT7\Fe(?n94AqBl+`.p!KY`s>37DkIahB8UMVrMjCXem&@>6.2_FBbmh9oMR*J-br,fW.9=%,Qt'02=4VWdKjcHlq6hnPk3P1W@$5,1>UhF*DP`>_i7o#3q/sZUmSpHM[%8kc7d%TJL,#*d2aZ3h?8/1?f\flJqa<0F%_^G4_5\a$=thP;1eu3l*e[BP)dmk?;)Qo(O\qZUA/Cpkt,VOa&i@1!3sNG)9^@jpR6X*qqkNbO`gH"&Lk\N9QVlA:GRsEY'P;iF_L;\CZo&30B<-iu%1-jG3X/eb=`=np_8d,\R~>endstream +endobj +xref +0 20 +0000000000 65535 f +0000000061 00000 n +0000000112 00000 n +0000000219 00000 n +0000000331 00000 n +0000000436 00000 n +0000000641 00000 n +0000000846 00000 n +0000001051 00000 n +0000001256 00000 n +0000001461 00000 n +0000001667 00000 n +0000001737 00000 n +0000002032 00000 n +0000002123 00000 n +0000004669 00000 n +0000006867 00000 n +0000009330 00000 n +0000010195 00000 n +0000012054 00000 n +trailer +<< +/ID +[<858c158945db34210779d20e1c06d94c><858c158945db34210779d20e1c06d94c>] +% ReportLab generated PDF document -- digest (opensource) + +/Info 12 0 R +/Root 11 0 R +/Size 20 +>> +startxref +14641 +%%EOF diff --git a/lab_rag/Lab1_Eksperimen_Chunking_1.pdf b/lab_rag/Lab1_Eksperimen_Chunking_1.pdf new file mode 100644 index 0000000..fd19d02 --- /dev/null +++ b/lab_rag/Lab1_Eksperimen_Chunking_1.pdf @@ -0,0 +1,213 @@ +%PDF-1.4 +%東京 ReportLab Generated PDF document (opensource) +1 0 obj +<< +/F1 2 0 R /F2 3 0 R /F3 4 0 R +>> +endobj +2 0 obj +<< +/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font +>> +endobj +3 0 obj +<< +/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font +>> +endobj +4 0 obj +<< +/BaseFont /Courier /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font +>> +endobj +5 0 obj +<< +/Contents 16 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 15 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +6 0 obj +<< +/Contents 17 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 15 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +7 0 obj +<< +/Contents 18 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 15 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +8 0 obj +<< +/Contents 19 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 15 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +9 0 obj +<< +/Contents 20 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 15 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +10 0 obj +<< +/Contents 21 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 15 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +11 0 obj +<< +/Contents 22 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 15 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +12 0 obj +<< +/Contents 23 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 15 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +13 0 obj +<< +/PageMode /UseNone /Pages 15 0 R /Type /Catalog +>> +endobj +14 0 obj +<< +/Author (\(anonymous\)) /CreationDate (D:20261102105336+07'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20261102105336+07'00') /Producer (ReportLab PDF Library - \(opensource\)) + /Subject (\(unspecified\)) /Title (Lab 1 - Eksperimen Chunking \(1/3\)) /Trapped /False +>> +endobj +15 0 obj +<< +/Count 8 /Kids [ 5 0 R 6 0 R 7 0 R 8 0 R 9 0 R 10 0 R 11 0 R 12 0 R ] /Type /Pages +>> +endobj +16 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2499 +>> +stream +GauHNlYkOd(B<7+iW)>CB1iq9Dl1#]dWN)n]+3MrpWYrhgPj,8@:)1+"m@%X%k3?u*F$tAjF^p'aZJ5$Fb&-DG+B"tR;,qK4?#4i(eIkTLRNe3]kSn3/rU',kq2ioIW"``0o_u'@+YU.K9)[cq:$UE+8_%1KlVOLi+DHgr+9uj2\#sCbGp7T;*m;StG34_**6nAIM^aG^)fo!W%q\rXIQkQ'ae"`F!_4uB2k!t^+Jmfsq"$`f%S_]*h_]rmtCEZ]fJmi")n4m_"(>tW.6nDhFJ\K&b.54=:A@[L^1Ac[AMqR+VC4lbfC&#(>YO=5q^WdBl'RY=alq^aERmrqg2Y`#1KgE-!AuuBdRK/TZNA@i$gGJ(TOCQs(jST$IL$'oc%m1U&L&-Jg>Ehq:rn-d)*!6$diArL-]iYRV_eiTH3#8IPMIStZh_*3)X\mmcAF37QI]=Q*q!fab_NO&MQ=.G3-+-sR>0E$=7\s8?9$*u7#I[:ks>\2^O%_-9Xa$'7n;1$,lJ*-HC<`*8USi,dma0YCV]17&,i=sQi'4ZZ<@^94H]5Sea'K[[77^kWRUaP^hV4qciM<:9u%;'f:P3"UASU,p"B.\)q503[B\(&CM>Dtf7h["JTD6hCt`i12ui00,bD#uhVYQElHX5j2<\cn54+g+qSRR4(`T:G,HL[R2WCK;-S9[Q^gF*V`PXF0g(jR*!.66Q&J+kHOmuOVZ[pk*'I.@R@rV2.AGqn@ShNH;AbnEGa"9lM9qY4Fk8%%ZG!Y_Q,S,nnRj&i"UcfL1$:rf9U+N6Jq`HD@$+hmpB;QLpD-?&a*i#<0D7,IpIl^s`SG5"DM_+UF6@ZL!LAG4<'9$gSJ>Qr];BC_WoOUf<)"21:+XH_7`]3]0Gb[/S&n\Z>_8r\!>D"E=C,_328[QY@%fG&Smtl4@?W?cX9D@bs3G,;2eE5c!_k&eU"#aL:Yi#:]/auECf9#\Xud&ULt*d<;b>SjWUi]0XO-bgDZUSQS?Aq!fVr_;U[0BCf`^8W5R^9S4>>0pTBc"['QVItJ"`@WN+WAt3ZTPfFtS2J\$#bBB:8%h:R'fe)1gBe6V$kSm=nA@;)+[1-RAqKd3%Ke5ca8ZIV)F00&VT6[F$5UaS#F>,22-?c1O\^D''QK*[LUfE7AgbkQ"HI:`bD7H`WeZ/B];8kp9p+7Rnef0pHCHcudb#&6L[h1<9eu2iS;umCQAS'V]I`Rc#Hg->oK]fl7'UDd!)W;qq84g+qT-_$Z;@,!mOmQW`"7lfsg-H.f-9k>M8])G3!Er7J_5GHlrn?.om"G76I&\m>bX#c[J+\i4?ZTB_2#b#^X&(\E?Yj&_l<2%fVDFRJS4]Kl"F1\_;n&(s5XWij]UCBWr_^5p!3!qb8LH!f:A8G]`GR@6:u,m+r*C9,@gA3^Rd)r<;G]"kBH!Fendstream +endobj +17 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2171 +>> +stream +Gb"/'>Ar7S'RnB335@3j*GeGJi`l75,jC%p9oHB$\!ObS(+h8(.$Yu\"PAdmG:6Tp>,Q)d%XSKh34;3r*Zfcs_aY@"?fXH'-.1D/If:pn.&Q*\U>t1!QC%70o&/=ipL_]((;[A)*_aFa0obDW^F&%K;&;Bec%C6qS't4K7.Vh$AP%ZlMaEXp;uD<72miL>_nEoRgI]jRQnIAe7'e9MNY^(I&j5sZb/d:g8n"hqY(RAlTc\`-]o]*'VcY/),FSdb2tJrl_rm;&A5.noKGdW3D\+36iO>['WDtbJT6,Cac0I%jkd2+I@3%LtCMA$nVDBU$d(f4J5']TlE-,irg8MCl"^PdlMaF7]7t&oTj!b_G*,6O09a3_@Oq9q;YR^UBFYrQH1-k99G'/d0b@A]I9Vr2FO5e($,dV*(8_M)L_g1H.-KNF_U"_gib;C91]!lh1qd"`$Y-Nt[MW%U:/eNe9SofQ&rq2]NRWsQ=*TJiA`[_Dcl3sM:5ogNP]``+i>579q!B(US]1PXGPC#MR^Zr5[DJ55*fK2P4Js9u5XQ"uk'ZH6'Mla=1nF[fJ!9X-i$=12QSnA7!VfI3WW\g,q`Iehhgep^\#=R`Wr\*Z=NQ/%hV%SYD,'/N@.BMhRt](o]sPC8>cZp2MJ(SmlY9F&Q&?;$fI0H5eYp,JW&+i<5qNup5OV0BTlc_brjkJ@0\i.`!`oF\jH*O_#97kGo[*#f80S/9<\;TkmQ'RV]l@g:f,;8flRLH-W_30PW<3OLX[VVSX`&kGJ)9Od9EI8Y[&l*pOrBhKOhc-q:78*"iDDi;NQc6N5++0fQ:>JXmE[%2`5L#[[s0EDAJ*NB=t=@knjue:i`EF-baFa#]=\\9;2O:l?U6t#'WcbPG+sthX"kN.$MgNN4n3!hA%C5DRiD/75:?%oO44%0-;d"chskc2LS'c%30"gHUX/M[e*gU`DV=n=r&f_57c2N-s+?M.PT>loQ[hYi@?O\Z/-7k9[87PU?HJ4]iS5,hbYLp/O\3m'GTiFbN!7^m"3UVG[-VMJu_a`-:eo(ID!$rQflRW71"'o>pTW'kJRHplO;?]QI/!2kE>.F\W@*'oWWR:QT`BN>0;1)\a%lM9]KS4bRP\ge+)e7LXlA)a0U61I<:n^P87ab71k%,G_Q62Df^D/;&G%pV:6;h4Z[n.c-K>EYX0*a9F['S/GLV%WINP':61`9X%b/Z\'!+%e!lS/0%3(g4!due+\,,m$LR]T5.7TJ*IYc/M?.la-5ZhRu6:PV-('okk3EV9Gboq3p@nD6,_VDWSBPW8W'RDd.(cek;QB_%.,Vk]ri8$`c?g$A`Vs*SbYc,,M,i+t-=:VKHRO$`i\QG(0'H\#Fj)\t*QfGfVb;I@Padr%h+p+g2)C;IT2qm5UaGXI+t@G,lPPA?LU5[g"k;]+jR&3X!m2pZ?V5tE.!F:I>X;>=Ti_-kIBT'[APHCR'=-HZK&nK.E:!K019pHVbm!9q3551CertXsu^Y]cJM1hBi+VLYUbGJ^V?Q["p]XiR/]^c-]F\k/DC%Zpj#l>Dthtklq8:iLNp!/:P>2T=fB.rd(qqBWV'[~>endstream +endobj +18 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2524 +>> +stream +Gb!kt?#SK='n+E3\3Np,>=`!rZG*s^$Tm*TS_/M*f^SR0TBsjf04?9=i%K1GBl]8ZG/kQM1h;QEqkG`:><-5F.B1$^MZ(+%=Z3^pDY'f*2-;S3EMZ_MZ3%9B58Y1`S.bPE4VKIn4r&-"Vt(e2rdk+\G`@G/X[9%ER$/ehr>dGB,s&e/9MT_JGsGP,"0.U_iMjdneE6!ZPmR%jls5sMEX[s7]b=dY)+`f#PuLcO3gXhB6aW]\d0L:a"Tf"uV-B*l88NN-`#$@R;JH&_/m?]0N\P(bfjfdU[3?&P9*!]e[j/6LfV>1s%8pd$JNi=`_U9=_"N;&lYMFr7A#fVl[Qc;UEApe0hQ&<:m!E?dDu4K[.?'Ee9P\Cj.Y]R(2\8gh&4#%3OF>TK>eX#l]XUHO^LN^iRt%^s7BjJ?UZbpQ"`SUTOFG'r8ZEge<'#dZ7^.Go&2K`Pd-MNFl\3Z?D>UqQorl1d]#Y:\`'Gkt);hn_X9C.!7'ac3Z1!6%rgIoj6O2mT:\7#'86Rdrapc5sCJ%)Wf&4RP`R\uZ'@"0B6MqdY[#Sh(I+Sh@-D>I@<6nhho&"HK>880m6d)Y"'"9*BA^6LC_W69uG&+t&5@HPDMJgR80i:h*/%W^/12<\;N!Fs86/."!FH^D"jG>iQ3-`V+H0HA;&`>DAK&c@47e\3b.VC6X\bjiPJ8C]$"kW7jeCQ:hEFM4,N;U^@DeI)Dc$_.?UcOV^<4_d7NiFPSpq@6iq\64dOT),OBjYs8n>1Sr=[XiWHVDI*_:nqS%j-\-/.QdZgl1b1nM\'dn)F>WM$hQMl^Gs_6rGsMn\L6V93S'HgXQHiB15iUOCT1@I401'2:'[q:*U@#ZG+B<_>3^)"gc^XZ#BH+XX&`pNu.,5m/:IQO,o<$k%/_M4MT],FL@SWcR^M^c[p3X)rO5`]%Kp2c9]:R48"W`Z_Fm?>k3/H82X&[^D+9JJ]R,k(Z%F@f2?;Ba+&DURS4ump0%*__/W93_bfkh?HT#qiju%1(uN1N2]:4nCJ@jpGt'kNI95b%i0>:jl>#`AJaTU%bi,e?<4ISYkC5#?p56Fl32j8_f!C)c59*",XY$(b)jf\;BR.V^2CK?5)[+qO.$,sfBi7'foPI&nq*-]&2Ge3bYQiGm%St]5!$f2CZsND\)]5P>>^>B:I=;]N+DT.@*.(4im%Lt`,6RdW4)"Y1%q(@RhJqRpf\kEgK*i^,Gad\Z+aA#5LWf5KJ]no*f3*oF!Fk0^Uh8ESZ?DhdQCMS)/&mM6qL<7J6G<07&\\B<42_`=J$.5;$)qd('`)$UrG7:H3_PTJ@FYdad8\PIef7tgL+#(RqMdq%>dZ16f3+0a7qNK't3A'\9ZSkPnihB0)Q4M`*=Wh)_b_DG;VR>J.b4G!VLlLB+j"]L:bX49fBq0$-2V[J^7#jjHcR9rYccN;cguLGoDp1s,(H`5'(h,s`K!F-Y^_hDOA@e>]^fgPVuh_6ftR$nQ9+'7+IeAd5'm_/Ck^cq#os'=c`fcX!:?_._h93tt!s8Ub[o"4i!2bg.S\%[#D8GRo)2h(`6(=B2_!m*:^.K~>endstream +endobj +19 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1164 +>> +stream +GasIf_/A!s&A@B[k$l+T'T/\3MR$#le%eCU5V7*%ASA6geT.##P1rK4A"b8l1TZIenf$kNfGJJro2E*%A:n@/<-r`\kd"+jO&FKm6P]2F0OZ'[@2k:PR"Y0LdUrY]U6-CO0SPgVHjmNa[aL_T7pcR!VW9*K^'k+_T34"bODWBM0I+";@Z?/_i="o:DQaV7Mhr2#@Riq54fso_n\f.3!fbR+omk92$-p//e:p&0,s3/#]i`4+:Dfor/X[V(8aJ.WR_J%nBlr"A0pUC:F3_TX:)JgqcQ=Z75&fH)E.3OLHe<;lT/(ir?M*8c!5:fb1chT.=J//*5<3/3p6BALaJjO+LGH3cFTGcCM+?0\S_?][c*70mELuAo*jK>;aGrg35-WE]qJ=j)'Dc%kr5X`&o;d%Ln.AM[''UD+XkZ'OIiHh.JX*&ifr[+!h@2I+K)9"7ulIp?AG30p(cX+FVA57oaL]!U=7X22mToNIMR$VSjCEVP7Y',,:9,e=b/nu>&UCK90=?t1[Np*7aP`G?)1Vlt!THO`%duA)ZYBhR^K;Wh9E\6OfdG/6Vi;Adp0:pjjV=hq0j@\%>YFARJUoog^qUbuK`3?qg8RHSLg[LW7E2@qu$bl3bIp)Q`a8:?Fdf(L0+Bl3.S:1]+$uDK'aj_P:f75G+rql2~>endstream +endobj +20 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2039 +>> +stream +Gatm;CNJ3!'`FV1EN;b[E^CInitp0<"p`qp`e<&*?QrRXTEWnm'a\@MC5&:*k/6Yc9<7O"d?tQ@A[HM6SZQc2`1$17&DGu&_2ua1$o([LsjS?%G+#45MJlnNSc<7"U7SSb@t3rVI?>eP^)703ofQoUuji99!3YY,$XL>E!"t^juR!,dbWaMl@+K1cY7]dnGm]'P-VC4HU-_H),MRHs,B=@X@2Q>r,,=(,Pf=/N(eH),-,.q`-(mY0[fa+\0Q4Njp13*H>p(jL3.s<6ouAY!i;g;.MH+"a)8>d*"Cp1=4ST(u`pFe8[.\CoJWC%])]@L'#BN^6H`SU]CX][Y#Kq-97',b+P&b7.*-o"n"M'%_[9t>[rTTq1c.o>KNL!1i:5qp,*19W-J]0R4-kOdD,0(Dl,,jd-Yt"L]Pu]D4NQRliH7\2cCGj`a%n=60^ZS@7bh-fb@L=62(KfM&mn9lHHpq3`rp:l@';gnbWV\W_"c^bK3NX@%!>@J6"abZ8H#ri/Pl!P$%+$6@k'\Tq9,6=2ODJ6,lLIQC49];\q%[K$OqOnIL_PcuV?h:.*3"R"1D?p"q_quDYE-$#?eJiKHDfjN0\sT*R&$CZ#0s>:q2PtIYi-T*`OaAnK?1tLef;p=&#D54[hK@CD="3_&s1=(;ZdPT$/j)-A"Kj3b-7Gn2fk^:cFK:I)5[7Bk#/+"_f1TW^%3rr`[;in?Yte7#%u!G.CNTruMcJi**a1o3!X`lH5RkSJDOTU':is+!e?aL_%n"Y!D8QEJq^c$Bl>B%IR]lREb1JeroJ`>EY>c^CTr]u:$C+1DKB+H3B5nun6PZSjl`(*/2uk%iuSi[C2!%1`qt%,S3e+=6aVTPB]:4N@1:\"JR2QP[EP`kE,O^ZrZ_sVZ,kchq!r#V3?OiR#&C-)[>h6rmGt_@?Z+8!8n)"IkM*iB'm]jY[rSZ34;Yk?'[9UB4`%gLAb`H]DYeHZCQ^i`\o+c?)^0pEidBlEn'c#>KQ$Y*F51fd(=,X9WIU1N4))5![OPr]T??WiX:PqUa/lh/]Xh\CatZ2s;L]*8bh#PY?_U724^G\=nIlciI^V(_Nir~>endstream +endobj +21 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2054 +>> +stream +Gatm<>BA7_'RnB33/D!P'1];@E\eOZ%&>T(1o7'&;+@Xh[Cq^0;HLKT`V"`Lfo$hCZ4"n+)%q5hSF>5dU'G!%l'^Gh']A?ip5-5pr'kM3Kj.,_BiT%=(r[(QQ*t>/q>"5(I/#Quc`EDSaIC(Q?P12=U[L0&M0SGk&u1nEf-Q83CA`,T4u4,`>2%&X,%O1#[PJS(f<"i3Bh6*TWN\nI"Fs:\7I6Fb($OL:1-I8.DcZ3"e,ZI8`QNIGub(8IKdd`]V/.97P#_ZSeV[JiSSQm6_p0EJJJP!r/,LA5]BNo'Q2#%&J2<=g3cUB.A)b@`$Ab.M4j7>l=GWSd+a4n$H%qnc9=N@1SeLanflqTjAo.`&Hq1u0&N3e8lIc?ck-kEYU7;lf^dTAC/$Sjomtn]AC#u^b$pW6rXpoN?X@?pD1;Sbk6$g#8>GQWA5=O'itmkKV_KWhA%l@"^sTL[t;mP3lpf*JCT_foDEoB1JLNAB?*WAkq&gh`Cqs+.upJ;N/gtf`4PHiB70&Qf4A`hX52Vin4WoDi'@on%g\4IcrIPu[8EK9Oq\VEqg&#Timm+PUgZkt3+Kf,c-[oQ.&:628M*_bXY*OKJ"i)/lX5Yt0"`<_G(RO(3\+&,&^_\DTh/.K@mS:"n?KmaAnNcLItN=!i9-AlR-gAVnlSK<.]B+3tX^9cLu^X*_G/R@!N*8s6O$^8Zq<>t,,?&r*..CN(I"Nj=cW3\&R:pnOX9<>&U][;H2W$=3gKn0gGaQK/,jX7QK22&J%I*p%'=m8o:qeE7(Bd+$9CfB6Y&l3U]59?)3)Z%c_Aabom1ZskjBS7EM'qjIZ!U`?^2:V`-'AP7j3N(KifZogI-F\90/6)oSQ2R==TPENdV\H,qma2jP?$*B"\*tYHfKFD$kGL"O\hk<-8Rt5]ab7tCp&RTBnK\4"FkT+19I^AdD3e(O`6(C@XVTF6M6i&NqqELb"-3U*fj70Q@^VC4&.9JXR&t"h28Y@7u0;d``VIYFa?E82dd2u8j,[RuTb`7@E>Lp:,Xo2_`7NM6)H^_0dAa&EudT]pr.j+-BG(5A$8==>7DEX)n`jWu)XD+U*`kgXDF]+qC,;LT`9C09>L)X,Eiggg^GO1JmkQk<(O\O9,<;cKPjbH+Kj$LC\#r;f565E;o`"=WSLBPlZ*;m^dPC(\:4l_>cQGXi?ZI1"2u3JMXO,HB);7ZJW0Y'4;BAtA95/_.sZ3"LUh,l`&,hpRoUKM*_N_M7SUPW`b,OCjcGeG1K-m(Q]@Y3LguaqRX8fVL9bq@RUE$DZOddJ4D%8I'_rIAQFIa.;WEuiFIen`n3Ogn/]2!Emb4t6?nGo=;j$!bdG2Bprq>OP0;$QC_lpta?dIXjoX\>8kSY_q0$ITH(;=uuC$6HbJ'dIFka>r)%upCY0gAoQ^8\&Ge&D),"K=ZuKCXX+qUOW"=e0f-lE&)Ld#cl+oafXbAp!4A+aKEc?jeG%3lg@uXuYQ,';k,^Hd%3io%1RKA%P'%aIUf@endstream +endobj +22 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2109 +>> +stream +Gatm?#($0T^&]5`%[E"sCu2'7>J"rmXR8sQj0QO58\u^um9,e"A!Cs^=@0QjV_%+s^+@B9WPDEKdX4LT'=/7&L%mm+Kr.>=!gt=QAYoH*n!]]5bPTa1pEO'IhO"skJ01>ocQht-F&N[2rQL/g$lK-O7=74[W3?;]8%d?CQ5%\T^sE(JgH8FOUY^VoUCI5p`ei'XR+2rX5+da`:?aee,SK3e!m@338OSe7-:K885D;_%.BF_>9?uI-9*-/M+`4.rZs]!9U*4feT8,O\$:/EhqZthH7*?l,+^%%qdkgkZ-qp5Ku7fA5908i]FH)Bj.3@[RN"a#J"fZe--4ADS_rMEiZE@I=.o!57G2d#/"/U*fI5jc&$$3gb%L9K8o4brD@"OWK7sRV7GSC1E9g"S0(`5&rkb9/Y4&60p3N5*)(g/?j2B3B1:IGZt*fH_N(U*ArFRGSY6$7*1->32UU5!g'XIk01\';p_`65])JOI?fG`&:jlZ/r`O)\0lYICkoo]7-@"WIM.WnLY@5sg/nTtDOFRfU6[E9C#Y#^bSGmI)_Ic%lG]q12loDPf!f`,HF4t"l"m;[m$LPs51j6]Bp%

jp_;/k@4U).?'Z042[-@B*tB2<2H*o&T\F;-um"'t,*YTfuJUa7(R,2q\(P$Zl_:sF:lQdPhN2X3#jOlTdaY8NH;*c`DRee;=k"f7TVH>R6[tTM@"ipdhJI+jED(DCTLR".V^Jl$(>r1Kt;PTG##X):c:fhg4N6Z?0,e'nB^[PmEKL4P9=!_AX"gdF&d[SMIp>Yi&9:#:9Ig@>N[3ger\n8:7,;>1Y&X1a9s!bm/rPSU71r"'-CQ=W34iDDo_P^`C&EF+_Q?RutaeLBSfS41-`3%]dOaU2M>_AdY(dEfF9e-7F_,gNDT'sPEPqk7XjCKnfUPN&KR>89#NF>+P2crB$Mp,%D)**:jsLH'D)]j?H]n[-r\0*1ACmL?Wq]+2`#.@V*bd-RsfR_7dnA6p6*UFNPE2A+]8%>l:f>$Tbnc)[+9bV;cC$m%pq8trYBd`#/GJ'BReSL\+aGr5&9MSk=M=N2!WM4E`F>lSUjh6XP[dZI4PR)',mpfg#cfQg\rFs_*jeKI%5LTI5FZ-N$"e6c@XQpX3'ScW.R!N??[s,Z9^0P1\J]9\2c.r//atK4A.Gp_^7l.*Rih;BWGe4O[j/hV>eKN=_2nspZCWrMcUtS9&)g*%C&~>endstream +endobj +23 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1821 +>> +stream +Gau0CgN)"=&:O:SF=EJ1cH7no`5/6o+GjC'NO.qFn@g#;24tP?-&iUQPcTf4ms@M?DN^33=X]cE4EJ+2FSG%9VCp_KnTti[]q*NhND4SW-9g*9Xd:lTVJa"9"92l`thS^$=+@+,#:N;0KIBj5aseT6,/P!;A-%0Qqb3!mF'iCHS_u/FSoV*=m11K2^0f.QH%DV,m$f"(DDo?-.#[>[%$>t:CCRVueLP"JbFC\E0T;8%AjCc!;>\jgHmhm>DUB+CO$2Jb<(R)3(%`2](AjN+')RFA-:-rSZXA&ZnA$N\RAPiQ7mI\&@Wm[cD/%!Wsp,&dq\9e*YB?5rQDH)Qr"Z*HAHbhAg>2LjMNdX1]s2hQKIkF1[?QGbiWGOKI1_?b4K,(qq^&uJ^\6`cdKmJ+l48\T2fk-fUWA-l%#`23?+B2!i%j=H2;NKnbf1&&.6Wm-+8!l'>=OIXc0NG::UN$[=L=d8Bq2jd=VZ"/g60s.Hto[>H7F:QdDmjue?\ppjXAU+.@[+8]uYCiEXgNG[&j*mN(LRQU.+,5N#d";rH?m*5-Y0(9elEd@ioGs\,EdZ^8+oN(#6$7af,!$WDUi!;.g#Wf(i-:6,tY28&UcA#&_61",>I&99(bShG+">K]AdITtOVGlNX%Zga'C^anb)]E%SH#7J:rJ.N\AbhD%TVj2+7;K.94Q;"Bt#I9MlsL@Li]QdJGMA)rRr76P+d/7c8.:r*FDc.bIAo$Th:8&A@/_)&ac-l+RA'/-6HAeSo0BVVo[cXW,L'O/D8nX-qLEZFug?rXUFCioC)"k\)TREIPUmZ7Y04J/fNZY$(&1mlS$lAml,)8=n0#PeXr"\ZM@C:"E9a+H-L!=4B@cqf"lWlJV>Fd$`s3Es4eE5TD.#$s;&qZg'NhM>Ns&%!?`(&i2Vendstream +endobj +xref +0 24 +0000000000 65535 f +0000000061 00000 n +0000000112 00000 n +0000000219 00000 n +0000000331 00000 n +0000000436 00000 n +0000000641 00000 n +0000000846 00000 n +0000001051 00000 n +0000001256 00000 n +0000001461 00000 n +0000001667 00000 n +0000001873 00000 n +0000002079 00000 n +0000002149 00000 n +0000002452 00000 n +0000002557 00000 n +0000005148 00000 n +0000007411 00000 n +0000010027 00000 n +0000011283 00000 n +0000013414 00000 n +0000015560 00000 n +0000017761 00000 n +trailer +<< +/ID +[] +% ReportLab generated PDF document -- digest (opensource) + +/Info 14 0 R +/Root 13 0 R +/Size 24 +>> +startxref +19674 +%%EOF diff --git a/lab_rag/Lab1_Eksperimen_Chunking_2.pdf b/lab_rag/Lab1_Eksperimen_Chunking_2.pdf new file mode 100644 index 0000000..ffa78f4 --- /dev/null +++ b/lab_rag/Lab1_Eksperimen_Chunking_2.pdf @@ -0,0 +1,213 @@ +%PDF-1.4 +%東京 ReportLab Generated PDF document (opensource) +1 0 obj +<< +/F1 2 0 R /F2 3 0 R /F3 4 0 R +>> +endobj +2 0 obj +<< +/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font +>> +endobj +3 0 obj +<< +/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font +>> +endobj +4 0 obj +<< +/BaseFont /Courier /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font +>> +endobj +5 0 obj +<< +/Contents 16 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 15 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +6 0 obj +<< +/Contents 17 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 15 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +7 0 obj +<< +/Contents 18 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 15 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +8 0 obj +<< +/Contents 19 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 15 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +9 0 obj +<< +/Contents 20 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 15 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +10 0 obj +<< +/Contents 21 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 15 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +11 0 obj +<< +/Contents 22 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 15 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +12 0 obj +<< +/Contents 23 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 15 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +13 0 obj +<< +/PageMode /UseNone /Pages 15 0 R /Type /Catalog +>> +endobj +14 0 obj +<< +/Author (\(anonymous\)) /CreationDate (D:20261102105336+07'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20261102105336+07'00') /Producer (ReportLab PDF Library - \(opensource\)) + /Subject (\(unspecified\)) /Title (Lab 1 - Eksperimen Chunking \(2/3\)) /Trapped /False +>> +endobj +15 0 obj +<< +/Count 8 /Kids [ 5 0 R 6 0 R 7 0 R 8 0 R 9 0 R 10 0 R 11 0 R 12 0 R ] /Type /Pages +>> +endobj +16 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2365 +>> +stream +GauHM>>s99'Ro4HSh+c+&iqM&q%Trjpg&j^-c<*1S)\uUuG-Tc_/#_>#(kY9gf!.&c"`:rDh&:VaAD".B"a+HfGfhW/SVP:TMU.1fi98?(+boaOM!o8l/-_;t\'FR/*!'54?sqUnhsgKr,rYtioWSs1dNF+Aj!X".)\a((ou=1r!QR:q-obb%6.T]76D;6]Rd[=R:cQ%QME;(2b_tjdpecf3o04<[p*XWUSF#ua;7)M\.nIthf?7'GRgZ9`$.\&LDbkPK\8iUG:MQ2I]!gsgN'2ag+S7>g0?IbW[\lZ4<^f$sZ/bVH6gVW%nWnop(`;6!D$lU*i-t+H/Z',VTrF^ZR%`8d#!TF1k,!DMtp"4d%fC?!^3bJBtHo([.`,-:27/^q2hXpOG]X+^E$f6@,o&\QVIM/Js?j01%5ldpuYO**0&+@C?;h9*tq.Z7%K"*!:4gEL\UY'N5/q0;9SA9\_*"GuF.QJ85a0@E``-IZ%r^_:hP>/mF>[&Y/#%at`sF+NFTH3(HB^M8I,T:"XFmdkj7^16qW66*mt<5@>UN@NTKP3OUH1;U;:=%dJ)FbB7(SRc3P:Fr$:\e4ICDp]3L1!";GT::8gECYQQY,9O$D76aRFf7EaF5QuL@ZsN53UegEkCbpgTRqu5aUr;>TdOS>+s:n63J!V$D@juURoPF`)J7h;X()K?_?c8nZ:/<>n$3"08AKrn?_Dp&87MR;$.VNpl\$1Z5@48=9@s7^m!hd=,?huWh`DKp0Oo'gDtf4rmdPNKlT\R&7!GO5$63RmY8:fA?(cfNSo(33P)&H3eQ=G^.rE[f2q#*$hc48mS;`MilFMHIa%>C#=]*)VJZC@`')oh`JJL5+iI>RPOcTrGFC6r;*aY]6AFBn*Y^A!Tm[iTg6a980;sQ0"pg2Z8):aa\CWhq[Q:n@=dOH'm`3)j:?0Elhn1Dh5"tB7p.1H*-79oP..C@'[_8e`G%_KV4OLN^+qLP0mDKe<,k9o1#@eT?_@.p\Vc\$LIh4B&rhF#[(l'K]5@!@ZJIV-UcA:Cu"kR[4um*`pC"*p=f:B)&gj%?h("PP28WGdD?2k:i4%YJja$jD?_0%R/f]P8lo*VL;6Tqa\G##d9.egBFR+JXtb$U??chr/PHe3_KkG-;1dW"^94_,@4p@[la^IK?[a0&UB^PjA/dVXu>)FND%@?VJDLHAB0t.hR+RoS:NU()V2G@'g"_2cf>Nar@FR*@f5P:t[.+l9RcaOWfrlU9J`&BIof3!&DP$:"P$;!p83JKG:#\#C=3m6qsV\OkK.+VVd&E4V9Pe#Lq7Rl^[-(Q3SSmaJ_Xf)I'E?N0d>")Ked_q-2oHK&QQMgY60P"_"S^4-*#4^".r!XPjR2Q+gSr*Nf.4rg$)7p^c5!)Q`~>endstream +endobj +17 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1970 +>> +stream +Gb"/&gMYb8&:Ml+$r@Y"$_&FkPIfhs8XqVnh7Blhk*M@?-J'N0luJND5X2tqQ4cbNEYTt8!(C9t[^`rUF#iF-0H_H%Jbr[e6n]>Jj6M5IO;9bh*.,`532=sAZeq?kI#JGp\];<5)bA>N$h8t!b#+mb`#>)S?kZW*>u)t!i0$X&_&e-T9_Pkf\G`Q4Ua(Xp[.@RLrJUAFl+aICVn[[$.d3;Q11dg6hDiuHOdF#BDpV&5b]6r>I/#XI/P`%$__LDAXB^nZ[^]_h^;O#AOZ!,[1rHI:HALEh@PXX%:@-0Gf\Vn#c".K%\pf"Y+t,D9&+)Bo-R6YDB(?)G7k_K8g_Y$tY97($^2,kf\D`M!R*#?)q"a]IXiFA:6HB)`Vt50BA;$`#*M6>">E/ZD/n3#rP3^5Y8sQKj^N%i8ZVT"!A="m4mq-05%#jlpBdOU9e6kb=o,j,W^T'rGEjf8W&SS(gErk>\B`jNQZlU4c3BR104K6@naNDLH:FZ%rMHhZT1eV/faO>?*Q'RG*>W'Z,_kD%hue_*99[d%;^t5#g_BFTFdH"[eRd-<)jA!l$:W>XkLA0_2r=QI.\Wi442e+*8I9N0]ZS[#?4/.%H76YFt!ciGP(:;pmCb5*MDT'Ao9BOdX&X;.ffe78!ZH+WdXaNJ1tX@Qf8Vo=5X5g]ec3\a=o44jk@C>EI!"fN-ql6[lTU/'5VSqquK7a'Hu6Dh-Wfp:r!JU,IcM"TeXQit-k`?=g8o#JTZU(,DLZ83bgTkE@5V^Akqiq81MQ`_XS:AGg<,q_n'E9/E21$^D!,4K_\9YV4XC=0mI(%@=Jl,B1QD;VNtop09LHh$6s'FUs`R%hZk1QSXobYgTJRF8fH0&.fg^3RsBC%QcdpGMIep9.m!h_I.QG&HL[WV@[G`eRK(iTK,b`d>BQJ[E%*D##59$kS@3&Rd0~>endstream +endobj +18 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2336 +>> +stream +Gb!ktgN)=4&q0LUFOaEl1g;"jPUou.4F&QI,dt)*=O*+:5S9k9OrsjYSt2n[pcT)UArf&LC@dOhPfl!j\f6XXV[jKi(gj!6\]]idDWps>64,*I\YnpJ32=_UIFt(fG1+ScG[_Q7S+0lE%[ZdKT)LVSD[7\KS?U^/DlNDQKKaCbHDN4f)'=.T:[RB:G<]Z7i*=CtYZKpk!J9/bn_dSGA-&qT&U3?,#1_CRrmr-EBISSVZ\In4r&)0',]:;i`%OXXP^"_-Z:FK`on=fZ"o@R2X<_A52snmt68ZY'3a_2k1(^,QL4Ii^ZMg,P1jYbs*!q&ls]%Q`on_+sR[K9tLO?];Ue*FF>[S%SfgGqehMS5:'nhtIUHaPgE.)h]'R`a`a,o/eQ[>e]FngCOgL&08Mts51b-MnisKl2]W!P<:IER/T9s:1s/_N6fU^*%YCrkk,L[mfCcfY]cl_GR%#(7\qqLQ\g@1@>.PgF5NnYmi9D,_^8nJJ;0a1gN*h45#-CH/F,R)Z8T]0b7]hlXGkOh(ctagd,KgS]j;lH?]%&?sTm?PiVT%'"Z>i[5mWPu1P=r3X@/kMq)-NqaNh(2!FnTY1>hP,WN-mgjQ=X$2ga;NfWa,M(?n+Gg"mqDPGEd:9SL^K5k;-K%m_ElD_b%+njMdh_d62bg&p2u6$k^Lo9TZ\l8N3[`X=RI$4mhL/68-]sC*UQgR&PgUPSkh*ri!IP&mI&7VR[o#d0;assEc\4pqS'M/VcB"X#c-b="pkip:&%ahHUp=N]Qpul1rWr>:)srX'e,u+Ir.TVM!=7:uQ:h?<%+)?@d>N'G2QCI7$$gA['hq)(q:EjH2-oSR'iX*@Y]e!D=0X:H"3?T18JtrLUKe7@e_]NcY#ZMODa:hc;I1ke-pi;+u_%!W\Vd77;&R4qGLp.XIFS+"u5PA#fG'g/7^+f4p?WPX5_M`Be$)9&c_)pnJ2g@[bN1G9":b?;EKitMp0S>,@EMc(nY/%&A`8a$BRBJYH^lH:N%0ZBJWI1TX#>ENb?TESLQaeADsmO5&X"hF5+Y@mg'K?Zh#:*Z5D,+&+Xn5O`LsD]5EDGS'gt#/]&WWbpQTP2/_33stZYq_r7J@tE)0`a8`&532;qa'43r(E`A!p9~>endstream +endobj +19 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 721 +>> +stream +GasIe9ol#6&A@rklEZ8QEIe<_dG'+]%XXR73-m$L#?md/S*o,-n$fk37OBp/N(U0Qn%JR\5sR*c5#2X'f+e.T$s3f"$a@%JL@c;[8/K#W6Y'g3M&-];H^fO30nZsmWiueG?k9_.02/f9LmZ5+N'Z15ne#YR:r<&0dPI\k/_r2hNCe-R`CZHD6^2g`RZKfB#;/.%VfrhW;Wg3QHFFBN:V:Ca.gsei\:P&&ObCWBg+[_5P7;L;DL'C@b,\YDHmD1%@U5#8k7[XlaV3)K4QgGltC@$If4rk`b$C5&7<(<#&-4'Pjg:(MYe3Y^N+m7iJq?>4K.R$nTTZZJg:T>trPq#R@.=c>e:Sq~>endstream +endobj +20 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2039 +>> +stream +Gatm;CNJ3!'`FV1EN;b[E^CInitp0<"p`qp`e<&*?QrRXTEWnm'a\@MC5&:*k/6Yc9<7O"d?tQ@A[HM6SZQc2`1$17&DGu&_2ua1$o([LsjS?%G+#45MJlnNSc<7"U7SSb@t3rVI?>eP^)703ofQoUuji99!3YY,$XL>E!"t^juR!,dbWaMl@+K1cY7]dnGm]'P-VC4HU-_H),MRHs,B=@X@2Q>r,,=(,Pf=/N(eH),-,.q`-(mY0[fa+\0Q4Njp13*H>p(jL3.s<6ouAY!i;g;.MH+"a)8>d*"Cp1=4ST(u`pFe8[.\CoJWC%])]@L'#BN^6H`SU]CX][Y#Kq-97',b+P&b7.*-o"n"M'%_[9t>[rTTq1c.o>KNL!1i:5qp,*19W-J]0R4-kOdD,0(Dl,,jd-Yt"L]Pu]D4NQRliH7\2cCGj`a%n=60^ZS@7bh-fb@L=62(KfM&mn9lHHpq3`rp:l@';gnbWV\W_"c^bK3NX@%!>@J6"abZ8H#ri/Pl!P$%+$6@k'\Tq9,6=2ODJ6,lLIQC49];\q%[K$OqOnIL_PcuV?h:.*3"R"1D?p"q_quDYE-$#?eJiKHDfjN0\sT*R&$CZ#0s>:q2PtIYi-T*`OaAnK?1tLef;p=&#D54[hK@CD="3_&s1=(;ZdPT$/j)-A"Kj3b-7Gn2fk^:cFK:I)5[7Bk#/+"_f1TW^%3rr`[;in?Yte7#%u!G.CNTruMcJi**a1o3!X`lH5RkSJDOTU':is+!e?aL_%n"Y!D8QEJq^c$Bl>B%IR]lREb1JeroJ`>EY>c^CTr]u:$C+1DKB+H3B5nun6PZSjl`(*/2uk%iuSi[C2!%1`qt%,S3e+=6aVTPB]:4N@1:\"JR2QP[EP`kE,O^ZrZ_sVZ,kchq!r#V3?OiR#&C-)[>h6rmGt_@?Z+8!8n)"IkM*iB'm]jY[rSZ34;Yk?'[9UB4`%gLAb`H]DYeHZCQ^i`\o+c?)^0pEidBlEn'c#>KQ$Y*F51fd(=,X9WIU1N4))5![OPr]T??WiX:PqUa/lh/]Xh\CatZ2s;L]*8bh#PY?_U724^G\=nIlciI^V(_Nir~>endstream +endobj +21 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2054 +>> +stream +Gatm<>BA7_'RnB33/D!P'1];@E\eOZ%&>T(1o7'&;+@Xh[Cq^0;HLKT`V"`Lfo$hCZ4"n+)%q5hSF>5dU'G!%l'^Gh']A?ip5-5pr'kM3Kj.,_BiT%=(r[(QQ*t>/q>"5(I/#Quc`EDSaIC(Q?P12=U[L0&M0SGk&u1nEf-Q83CA`,T4u4,`>2%&X,%O1#[PJS(f<"i3Bh6*TWN\nI"Fs:\7I6Fb($OL:1-I8.DcZ3"e,ZI8`QNIGub(8IKdd`]V/.97P#_ZSeV[JiSSQm6_p0EJJJP!r/,LA5]BNo'Q2#%&J2<=g3cUB.A)b@`$Ab.M4j7>l=GWSd+a4n$H%qnc9=N@1SeLanflqTjAo.`&Hq1u0&N3e8lIc?ck-kEYU7;lf^dTAC/$Sjomtn]AC#u^b$pW6rXpoN?X@?pD1;Sbk6$g#8>GQWA5=O'itmkKV_KWhA%l@"^sTL[t;mP3lpf*JCT_foDEoB1JLNAB?*WAkq&gh`Cqs+.upJ;N/gtf`4PHiB70&Qf4A`hX52Vin4WoDi'@on%g\4IcrIPu[8EK9Oq\VEqg&#Timm+PUgZkt3+Kf,c-[oQ.&:628M*_bXY*OKJ"i)/lX5Yt0"`<_G(RO(3\+&,&^_\DTh/.K@mS:"n?KmaAnNcLItN=!i9-AlR-gAVnlSK<.]B+3tX^9cLu^X*_G/R@!N*8s6O$^8Zq<>t,,?&r*..CN(I"Nj=cW3\&R:pnOX9<>&U][;H2W$=3gKn0gGaQK/,jX7QK22&J%I*p%'=m8o:qeE7(Bd+$9CfB6Y&l3U]59?)3)Z%c_Aabom1ZskjBS7EM'qjIZ!U`?^2:V`-'AP7j3N(KifZogI-F\90/6)oSQ2R==TPENdV\H,qma2jP?$*B"\*tYHfKFD$kGL"O\hk<-8Rt5]ab7tCp&RTBnK\4"FkT+19I^AdD3e(O`6(C@XVTF6M6i&NqqELb"-3U*fj70Q@^VC4&.9JXR&t"h28Y@7u0;d``VIYFa?E82dd2u8j,[RuTb`7@E>Lp:,Xo2_`7NM6)H^_0dAa&EudT]pr.j+-BG(5A$8==>7DEX)n`jWu)XD+U*`kgXDF]+qC,;LT`9C09>L)X,Eiggg^GO1JmkQk<(O\O9,<;cKPjbH+Kj$LC\#r;f565E;o`"=WSLBPlZ*;m^dPC(\:4l_>cQGXi?ZI1"2u3JMXO,HB);7ZJW0Y'4;BAtA95/_.sZ3"LUh,l`&,hpRoUKM*_N_M7SUPW`b,OCjcGeG1K-m(Q]@Y3LguaqRX8fVL9bq@RUE$DZOddJ4D%8I'_rIAQFIa.;WEuiFIen`n3Ogn/]2!Emb4t6?nGo=;j$!bdG2Bprq>OP0;$QC_lpta?dIXjoX\>8kSY_q0$ITH(;=uuC$6HbJ'dIFka>r)%upCY0gAoQ^8\&Ge&D),"K=ZuKCXX+qUOW"=e0f-lE&)Ld#cl+oafXbAp!4A+aKEc?jeG%3lg@uXuYQ,';k,^Hd%3io%1RKA%P'%aIUf@endstream +endobj +22 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2109 +>> +stream +Gatm?#($0T^&]5`%[E"sCu2'7>J"rmXR8sQj0QO58\u^um9,e"A!Cs^=@0QjV_%+s^+@B9WPDEKdX4LT'=/7&L%mm+Kr.>=!gt=QAYoH*n!]]5bPTa1pEO'IhO"skJ01>ocQht-F&N[2rQL/g$lK-O7=74[W3?;]8%d?CQ5%\T^sE(JgH8FOUY^VoUCI5p`ei'XR+2rX5+da`:?aee,SK3e!m@338OSe7-:K885D;_%.BF_>9?uI-9*-/M+`4.rZs]!9U*4feT8,O\$:/EhqZthH7*?l,+^%%qdkgkZ-qp5Ku7fA5908i]FH)Bj.3@[RN"a#J"fZe--4ADS_rMEiZE@I=.o!57G2d#/"/U*fI5jc&$$3gb%L9K8o4brD@"OWK7sRV7GSC1E9g"S0(`5&rkb9/Y4&60p3N5*)(g/?j2B3B1:IGZt*fH_N(U*ArFRGSY6$7*1->32UU5!g'XIk01\';p_`65])JOI?fG`&:jlZ/r`O)\0lYICkoo]7-@"WIM.WnLY@5sg/nTtDOFRfU6[E9C#Y#^bSGmI)_Ic%lG]q12loDPf!f`,HF4t"l"m;[m$LPs51j6]Bp%

jp_;/k@4U).?'Z042[-@B*tB2<2H*o&T\F;-um"'t,*YTfuJUa7(R,2q\(P$Zl_:sF:lQdPhN2X3#jOlTdaY8NH;*c`DRee;=k"f7TVH>R6[tTM@"ipdhJI+jED(DCTLR".V^Jl$(>r1Kt;PTG##X):c:fhg4N6Z?0,e'nB^[PmEKL4P9=!_AX"gdF&d[SMIp>Yi&9:#:9Ig@>N[3ger\n8:7,;>1Y&X1a9s!bm/rPSU71r"'-CQ=W34iDDo_P^`C&EF+_Q?RutaeLBSfS41-`3%]dOaU2M>_AdY(dEfF9e-7F_,gNDT'sPEPqk7XjCKnfUPN&KR>89#NF>+P2crB$Mp,%D)**:jsLH'D)]j?H]n[-r\0*1ACmL?Wq]+2`#.@V*bd-RsfR_7dnA6p6*UFNPE2A+]8%>l:f>$Tbnc)[+9bV;cC$m%pq8trYBd`#/GJ'BReSL\+aGr5&9MSk=M=N2!WM4E`F>lSUjh6XP[dZI4PR)',mpfg#cfQg\rFs_*jeKI%5LTI5FZ-N$"e6c@XQpX3'ScW.R!N??[s,Z9^0P1\J]9\2c.r//atK4A.Gp_^7l.*Rih;BWGe4O[j/hV>eKN=_2nspZCWrMcUtS9&)g*%C&~>endstream +endobj +23 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1821 +>> +stream +Gau0CgN)"=&:O:SF=EJ1cH7no`5/6o+GjC'NO.qFn@g#;24tP?-&iUQPcTf4ms@M?DN^33=X]cE4EJ+2FSG%9VCp_KnTti[]q*NhND4SW-9g*9Xd:lTVJa"9"92l`thS^$=+@+,#:N;0KIBj5aseT6,/P!;A-%0Qqb3!mF'iCHS_u/FSoV*=m11K2^0f.QH%DV,m$f"(DDo?-.#[>[%$>t:CCRVueLP"JbFC\E0T;8%AjCc!;>\jgHmhm>DUB+CO$2Jb<(R)3(%`2](AjN+')RFA-:-rSZXA&ZnA$N\RAPiQ7mI\&@Wm[cD/%!Wsp,&dq\9e*YB?5rQDH)Qr"Z*HAHbhAg>2LjMNdX1]s2hQKIkF1[?QGbiWGOKI1_?b4K,(qq^&uJ^\6`cdKmJ+l48\T2fk-fUWA-l%#`23?+B2!i%j=H2;NKnbf1&&.6Wm-+8!l'>=OIXc0NG::UN$[=L=d8Bq2jd=VZ"/g60s.Hto[>H7F:QdDmjue?\ppjXAU+.@[+8]uYCiEXgNG[&j*mN(LRQU.+,5N#d";rH?m*5-Y0(9elEd@ioGs\,EdZ^8+oN(#6$7af,!$WDUi!;.g#Wf(i-:6,tY28&UcA#&_61",>I&99(bShG+">K]AdITtOVGlNX%Zga'C^anb)]E%SH#7J:rJ.N\AbhD%TVj2+7;K.94Q;"Bt#I9MlsL@Li]QdJGMA)rRr76P+d/7c8.:r*FDc.bIAo$Th:8&A@/_)&ac-l+RA'/-6HAeSo0BVVo[cXW,L'O/D8nX-qLEZFug?rXUFCioC)"k\)TREIPUmZ7Y04J/fNZY$(&1mlS$lAml,)8=n0#PeXr"\ZM@C:"E9a+H-L!=4B@cqf"lWlJV>Fd$`s3Es4eE5TD.#$s;&qZg'NhM>Ns&%!?`(&i2Vendstream +endobj +xref +0 24 +0000000000 65535 f +0000000061 00000 n +0000000112 00000 n +0000000219 00000 n +0000000331 00000 n +0000000436 00000 n +0000000641 00000 n +0000000846 00000 n +0000001051 00000 n +0000001256 00000 n +0000001461 00000 n +0000001667 00000 n +0000001873 00000 n +0000002079 00000 n +0000002149 00000 n +0000002452 00000 n +0000002557 00000 n +0000005014 00000 n +0000007076 00000 n +0000009504 00000 n +0000010316 00000 n +0000012447 00000 n +0000014593 00000 n +0000016794 00000 n +trailer +<< +/ID +[] +% ReportLab generated PDF document -- digest (opensource) + +/Info 14 0 R +/Root 13 0 R +/Size 24 +>> +startxref +18707 +%%EOF diff --git a/lab_rag/Lab1_Eksperimen_Chunking_3.pdf b/lab_rag/Lab1_Eksperimen_Chunking_3.pdf new file mode 100644 index 0000000..3971b5b --- /dev/null +++ b/lab_rag/Lab1_Eksperimen_Chunking_3.pdf @@ -0,0 +1,213 @@ +%PDF-1.4 +%東京 ReportLab Generated PDF document (opensource) +1 0 obj +<< +/F1 2 0 R /F2 3 0 R /F3 4 0 R +>> +endobj +2 0 obj +<< +/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font +>> +endobj +3 0 obj +<< +/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font +>> +endobj +4 0 obj +<< +/BaseFont /Courier /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font +>> +endobj +5 0 obj +<< +/Contents 16 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 15 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +6 0 obj +<< +/Contents 17 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 15 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +7 0 obj +<< +/Contents 18 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 15 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +8 0 obj +<< +/Contents 19 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 15 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +9 0 obj +<< +/Contents 20 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 15 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +10 0 obj +<< +/Contents 21 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 15 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +11 0 obj +<< +/Contents 22 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 15 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +12 0 obj +<< +/Contents 23 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 15 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +13 0 obj +<< +/PageMode /UseNone /Pages 15 0 R /Type /Catalog +>> +endobj +14 0 obj +<< +/Author (\(anonymous\)) /CreationDate (D:20261102105337+07'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20261102105337+07'00') /Producer (ReportLab PDF Library - \(opensource\)) + /Subject (\(unspecified\)) /Title (Lab 1 - Eksperimen Chunking \(3/3\)) /Trapped /False +>> +endobj +15 0 obj +<< +/Count 8 /Kids [ 5 0 R 6 0 R 7 0 R 8 0 R 9 0 R 10 0 R 11 0 R 12 0 R ] /Type /Pages +>> +endobj +16 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2417 +>> +stream +GauHM>BAQ-&q801fU#:metED%2^EIAP;I9K[dLYbo&^f#AAJu(Mca;SHKP/#ZN*RQOsPusX>:nj,d>o_G!A4pD#>OSo.C2k5DP.i!lTZc4V64c@K%3nSA4jb76;0_$"j##\E2Csq#klUMb#EB/U&QJ/VaKQ:h#QK&=B@LqjAfojVa.9Qp8Ca42pUu'\"`**Qr(*,7o*NKhN@6Lsrf(hWA_Y<@fdU*?\$)kVu2LJ6<@*1rT4c&n\oK"k(,>O)^SG6DbrZ+'3S#b:J77)82\%B:UNU\!LjSp?P1N:Ub?#Yeb%\76fP\cWXP[P1jg+BhNA/<\igHJ'([/le<`3DQe<,Da0$t+5_LPo&W%4(Tnj\eN-(rnMO,-FF.OF0AC7RdVZaOERQt=aA/eL'bCbU7(V<#*3MM2!icd18C?gEae9>e\J=eN9)(S3WWWWP>cAB[Ft"(*O/NC:V:+<3N,ba!n!/KI"eKQubR5InkY=g;$8WDt]Tc!cp.Va)`C2_lS$P&oNUb@4Y;PJ(FWp2)7EVZ'/?_pp+V+fms!dOf"I@o-@C,Q;g6cqpX?"o#c@"TC7l,2=Z'eE-',?S.8+3`PbfSQl7"0p<'$eBZE-G$1>B%r9:;;;KfYM[\fa'>]bF$g1)4/AJK]_96X!%YW&Q'8Ot5Xg'cIj-Uat_$2BbfGBtfUe&5:^`*DgYg]e8C'8e>_OeS/>;g-XkHXR:Bu2(?/(_"Cu#JAmSW7;q?.ZT?!HMudM(`S`WD/Ir0hpYTiLrGFdJ?,t$>d)/icQ,)Y,;2B=OM64L3X'Bj[B+p.MgQViT7Ac"<\R-5Gec6Pi@AY"1Z;jokLrpAkO/[j9p3=k27m3,!?WT?EQ1]rMPGL7_AcpacIhL@?]7*Ra-&]%gIej!6o('\q],iY9U,[M8!l?:1k-MuI&S&e2.!a$i/]+f+.EiK:S-o\7C#_KBp^euJ&d4HZ!4)G%S>PJ*K8eKjhV2eT!\>7?.p:GCLe*q^e1\_4)_oGfFdh7;SN>Cg-$cZ_:rKEG(heC<'g-t\BJ-cS*&A=tF/\,&A#o:[U.BNXF/Df;bU#B-$ulf58:-h-4:3,?_aN@tES!E:BB/E:SAS:`&n6plnmqHL;2Fc6$$[CbT7HZ8oL-]qo<^m(LhqNP`g^Lf2TFcCSq^OJ?1a5Fh&kO.HA8RmZ(F_ui69\L$tlH/_Dj@%7rfkgiiBn#pL5C/e8:qUVTk$eVHBIuY;JB.?J=XrB[@(<0H,%Q9Xj-;/B#cAiN(r>gZ7.4Hik9HqTT)J[U2j5-*%^8Vf9]YPI"LrA;s5h$S2.8_C$kqHR18pMtdNKL+JrD%f-\,MM^6GbZI1;CNs4e&.iT3.k+(!`h6!pmEkuB)bWendstream +endobj +17 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2064 +>> +stream +Gb"/'?#SIU'RfGR+>=4C#=jslb9)!Ig9"S3/jM>)DgA$->%/mW)FZOiYTLW$W@t0RlXk"kM?6@"On\I;F0?Le&:Yo(F&t*iHHUd:4^q:4[X/cAJd'p.akgi@r:?Y4Z_eP.@+daTOtbT@,PLYGPLG5a[iVa(6+g@&fjtjclR65sMTt#KP#knppa+\OZgCP!mOpO:l$=7Q1SaY=&?dWVqo1aJ=kZllrA&0#A`9/D!J1[L[3JCZ2X05=FjUVRYU-$H'`=,Rj-JZ@H-mJb>@%7hK&=ZB^jVTf0`ND)e>'mbnV9MYnJJ%1!NV:/Uk*:#PTba#61E=3P.e4dd_Vt0XAJ5cFcf;B"(*2WUjK:6gqMsg:qAk`Keq`YRq'L1?q"B2pOJTqZo,[7'^N3+W5gh>)?3^JK%XM7N8%T603OMjrPlg;8KE2#=`7PG%kTPkIPPB$aZ7;l'N!B]^V4r7[gWjU1."rk'8;s3O=OHD,:9sB8"[h,gs(Sge;;Ltr?'$E;\)4/OLV.Epi[2PS9li=22;kUThINV.:.!J\O8tVg=kLd:L7O)B'+,F"YJQ$ZMf#RPH:iptRd5[#IMg-*eT;8H!iNkL)Q%g.T,jV4>--9`&H6uQfWoXPaMQA/p'82R"oi*Xi7ito,^po]oi_j*-m!?*dR*\%tH"'Gt;D+6+e7M/i1/`\ogcAm_/>]"=a"S>]\T1ZD#?gUf?Jt5SM.LWm/ad44R9`8O$9\B[.p#nWeKFBQ>[HoW_H(&Jc4QTJ/fcFj;/A65-5Y9s-JGgq"IfkX>hYbbU@K9O:Z#??:);!`ueDaM\=o'6rg`Pp2Is'794ABHO="$9C$b6]PB"=-l%O%5k3<.Y"pKQi^18*\K>8T`c3)\iLr0QcVob;2mrd[h*'AQ#mlA!gC1/GLj6$T;Q>-fShLIINV8&"94FRX!dO5P40[PKUXWfk:gBNL/-7bVWh_KFHLCZ4lLH"\lbJmV;J"o!6)!'Y.Z!a9+-jSW0rUHTE_-USK^l$RWt7n]L34BQkM"8;A?3pV(;n_*>5PX$N-X,:^eYP*t2ECi-ioKLkR\\C^suc>R*e3TE$t%,n&#P@7!>`\ksc].cG)+pX)Z67<:arlVAU;&f@RO=s3'e,I8iKSoB.1e$D3XWR?@S8:dA>O+]?-K6+h8,h&'(r'7nY]1+E*UdIMnU58f_pKR\:hCC7W;&G%(!<7=8?>^NkI=@W$+0DU)s6K-Sc^fc0\:4/&)QbX,YH?^6eo.t)d^2b@J%?]/^cN^5jbDLPJOP^\Be]Sn\(kXUX`q1@ghb#/_UlE)iPTie\l)F#I8NtQ1Ha)AeLtSaE6Gk9,,GH3kEG:7b$c![ctnWO?so3/RJ6ACG6skY](QiZ3&\R<1_Zf0NFJDSDMLBg6.Xag'04uC:)HCdpLA]Q`mgDTGcb_?6F2E5kkcTOGg`;U[`@$C>jC-q%htrP7;EbqVWIk_<;ih=R%_%O.N>iG_)/`9W]Za+lJ>Mb@+S@(f(tm\7b%eEe,l>WWR>e?".X[f,g?`O\4Gia./JU,_Ej0pL%Y"1_#:TS9DN-(O+M'^ba\!/pp'UdR;endstream +endobj +18 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2380 +>> +stream +Gb"/'gMRui&q/A5&-r?Y_5K0GUUfV8YW'\DnJ[Lqb*u]sdo88]I1+`81I+-Q:DNabc:kV%%1iXK%*2=*=]MOaVs:Kr0uq%rJ*orQ?9O)t^Pt[PLkd>ihaY*7iEtT6LT@&M\i1RSZ&Mf?o4U.F\#WVYr4gKi6ekg?ese)@XuBf%8+@pd`Bu)W^QX@&AL/*F`5=l'HpQoO_,7s]PshZiZAlhLZ&2q2MZBqE^UNL-[\[eEQ/5.aYNELqeDFL^QI1H"I/3.rXOcrD=#[+)YP/BBO*E,][F;Z_:YKM_M%fuWW]J3pMT4rUdcm]ks2=Jt\raPXik<,N^!i/=#)>:2P%c:dj^u@XVfLJ5C;rmbAW80MFn#$)X/_K0^AR/02FM^;`@^s-NNFGq7QFa4*a=DtDl#gWWp,-]CE>ct\koqNFJ5>1;_lkem"3c21G&=c6K-q,Cr"sk@$$]\[L\X[]"kqJl7kV>?BL>N`PRIdChb)q"^-0`mO>j+aV>u3Xa>"))-(T70*.SfRXs^D'an`X[HX7XZa>CLc:`<^#d]Ok36UB.g_-a;+BP\=qqOJ%#;n\<3:<`]WOp/:JWd,7Q+X+',&8Q6YUi=`-;T/)is/OPnGG`6g_Bg,$3"9-](iWQ]@(k:Y_(o-JR`Ei3*p^U&*pg`:IER-/bu$AO&U,ig>1E@P.Wi58oS&MKh.RM]VfB6ZT_D4mV^KaVI[o2SUF8^WEjS9,G^i<:$#"!lILErHCq>/EY@V':G.;(.>71<;WNrTk<9h[!,FRSh]0%Z*_1f5!3^u[&pj#_,[Ftg%?'(6X"&S[J6&G5a?6")(`3Y$NGlMr8V(-0:$_CZb07()45-B4?\:p8GUYXjHbbLcJ=[fa"[[uSVcm\4m6Iuj%im7^nApN0'JkcK?)pS:E&8*b'f45]7b8adkZ'Ii4-N@a<&\;j3%H@./;_;\kI[hnfOFUEMOl%a#BVITBc4+]FBuu5i+T]r1&JCSl'Vi`1IHbb$qb(Y0eo\E[/JEtN.N'rG)O"@?kaY0n+)D%&j4jjYCMRC4`%*1!qh1CN"\8,[&.b]lADQt1LNjF(e!eaLAI-oX]'0-g=-iM/K.cbg5jjb;U(C^C<"@_G'A(hG4G?:0]$dY[c)H&q&PpM?8pMVcbU^bAFq`"H`>HA*gs#'Ye_c[>$T;YD\t(T@kBC+0LW.KVM]E(@=AdGj(%O;3NbMJ9VUf)LWVY/-Vt>BLqV/1fWK5qQL"0j8mb]='QV`@FQ:_87g0RYN:DH;'D.IOFa?#Y?*,\Ln_=E*i@1Vt5>/']Jj.:]]0Z6Ru"rX.7R+TrD?[:gn)URgSeo>?jH@n8a]C9&0gO%(\m#^\.B?2klB!I;X_,.JWR`8E#bkQ]:-$P?=j))0+/2j%K[q6StYV-Q9^#iI:/aBh^aV&!0]bJN+<[G?+;^f2IX5jliBTNp-Df2VnW'%E"XBt0.E)RZ5TV%f`fJU)&E-g.Nt4["<:osPHF59kF:ZugjB4bHa)P!O7WSbn6W#m7_$rS1Ol)A]S&HfkVKbJK,t/JOCu-X"Pkg=0W7WkiVV6a?e55/%k,bQXBU`!o%fS@q@BIsq7Q~>endstream +endobj +19 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1130 +>> +stream +GasIe?'!u7&:EABd8G'!)f`l-Y`7>6]6rE`M*rU1H"lbuBDmBkHP.L`a/=4l#52G#X2X#]l)sHW.RcQ#Pl'7%7%[O;q,NOaBXK'Bo4GB+K76rdrV^h!REInU7Aoldkc5t,o_-u)jaoO)&)t,9,k7D%b#^6Fqok8-hKaM;5@&]VpD^:o4]#f*2eZ4sBBGuppIJW?39-edoATIM/lQo^#dI4Y(ASlF0Gl&kt9W>1#0P2`d/3qRUcl(B20H#=i!4FbtTFL?-Z`TU8dkM']E4&.-0tq,jSS_Uj6[F$i[hU,tF_$P^QDhN#SNDWt_6,lK3q0#h$WPi>*?))kPJjY`jar8YMnVeieej+[qcoJHc7Vq!2?[Dg7c*ML;2++4>*(]1;4,@opH;hQM*GhVIR"_Z!KW%didK`%^S;oj9_`cQO%C0HQ"D$3Z"D(R,t]$edo7QV+q=i+cl^)19DsZ.nHoc'Da-7s:EIKT]eE/eI4a;?uY2PS_0aMDaDRa;<1,.G=fq4`%Fg?*8m"SJl2;7<8@;.j/^0.3_Qc$NL>EHMi$61+RdFMc,J?^\OgrsNb+$o-kJ#p2fu%P:=mfP*#LI5K_aC9$#&Ip.muendstream +endobj +20 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2039 +>> +stream +Gatm;CNJ3!'`FV1EN;b[E^CInitp0<"p`qp`e<&*?QrRXTEWnm'a\@MC5&:*k/6Yc9<7O"d?tQ@A[HM6SZQc2`1$17&DGu&_2ua1$o([LsjS?%G+#45MJlnNSc<7"U7SSb@t3rVI?>eP^)703ofQoUuji99!3YY,$XL>E!"t^juR!,dbWaMl@+K1cY7]dnGm]'P-VC4HU-_H),MRHs,B=@X@2Q>r,,=(,Pf=/N(eH),-,.q`-(mY0[fa+\0Q4Njp13*H>p(jL3.s<6ouAY!i;g;.MH+"a)8>d*"Cp1=4ST(u`pFe8[.\CoJWC%])]@L'#BN^6H`SU]CX][Y#Kq-97',b+P&b7.*-o"n"M'%_[9t>[rTTq1c.o>KNL!1i:5qp,*19W-J]0R4-kOdD,0(Dl,,jd-Yt"L]Pu]D4NQRliH7\2cCGj`a%n=60^ZS@7bh-fb@L=62(KfM&mn9lHHpq3`rp:l@';gnbWV\W_"c^bK3NX@%!>@J6"abZ8H#ri/Pl!P$%+$6@k'\Tq9,6=2ODJ6,lLIQC49];\q%[K$OqOnIL_PcuV?h:.*3"R"1D?p"q_quDYE-$#?eJiKHDfjN0\sT*R&$CZ#0s>:q2PtIYi-T*`OaAnK?1tLef;p=&#D54[hK@CD="3_&s1=(;ZdPT$/j)-A"Kj3b-7Gn2fk^:cFK:I)5[7Bk#/+"_f1TW^%3rr`[;in?Yte7#%u!G.CNTruMcJi**a1o3!X`lH5RkSJDOTU':is+!e?aL_%n"Y!D8QEJq^c$Bl>B%IR]lREb1JeroJ`>EY>c^CTr]u:$C+1DKB+H3B5nun6PZSjl`(*/2uk%iuSi[C2!%1`qt%,S3e+=6aVTPB]:4N@1:\"JR2QP[EP`kE,O^ZrZ_sVZ,kchq!r#V3?OiR#&C-)[>h6rmGt_@?Z+8!8n)"IkM*iB'm]jY[rSZ34;Yk?'[9UB4`%gLAb`H]DYeHZCQ^i`\o+c?)^0pEidBlEn'c#>KQ$Y*F51fd(=,X9WIU1N4))5![OPr]T??WiX:PqUa/lh/]Xh\CatZ2s;L]*8bh#PY?_U724^G\=nIlciI^V(_Nir~>endstream +endobj +21 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2054 +>> +stream +Gatm<>BA7_'RnB33/D!P'1];@E\eOZ%&>T(1o7'&;+@Xh[Cq^0;HLKT`V"`Lfo$hCZ4"n+)%q5hSF>5dU'G!%l'^Gh']A?ip5-5pr'kM3Kj.,_BiT%=(r[(QQ*t>/q>"5(I/#Quc`EDSaIC(Q?P12=U[L0&M0SGk&u1nEf-Q83CA`,T4u4,`>2%&X,%O1#[PJS(f<"i3Bh6*TWN\nI"Fs:\7I6Fb($OL:1-I8.DcZ3"e,ZI8`QNIGub(8IKdd`]V/.97P#_ZSeV[JiSSQm6_p0EJJJP!r/,LA5]BNo'Q2#%&J2<=g3cUB.A)b@`$Ab.M4j7>l=GWSd+a4n$H%qnc9=N@1SeLanflqTjAo.`&Hq1u0&N3e8lIc?ck-kEYU7;lf^dTAC/$Sjomtn]AC#u^b$pW6rXpoN?X@?pD1;Sbk6$g#8>GQWA5=O'itmkKV_KWhA%l@"^sTL[t;mP3lpf*JCT_foDEoB1JLNAB?*WAkq&gh`Cqs+.upJ;N/gtf`4PHiB70&Qf4A`hX52Vin4WoDi'@on%g\4IcrIPu[8EK9Oq\VEqg&#Timm+PUgZkt3+Kf,c-[oQ.&:628M*_bXY*OKJ"i)/lX5Yt0"`<_G(RO(3\+&,&^_\DTh/.K@mS:"n?KmaAnNcLItN=!i9-AlR-gAVnlSK<.]B+3tX^9cLu^X*_G/R@!N*8s6O$^8Zq<>t,,?&r*..CN(I"Nj=cW3\&R:pnOX9<>&U][;H2W$=3gKn0gGaQK/,jX7QK22&J%I*p%'=m8o:qeE7(Bd+$9CfB6Y&l3U]59?)3)Z%c_Aabom1ZskjBS7EM'qjIZ!U`?^2:V`-'AP7j3N(KifZogI-F\90/6)oSQ2R==TPENdV\H,qma2jP?$*B"\*tYHfKFD$kGL"O\hk<-8Rt5]ab7tCp&RTBnK\4"FkT+19I^AdD3e(O`6(C@XVTF6M6i&NqqELb"-3U*fj70Q@^VC4&.9JXR&t"h28Y@7u0;d``VIYFa?E82dd2u8j,[RuTb`7@E>Lp:,Xo2_`7NM6)H^_0dAa&EudT]pr.j+-BG(5A$8==>7DEX)n`jWu)XD+U*`kgXDF]+qC,;LT`9C09>L)X,Eiggg^GO1JmkQk<(O\O9,<;cKPjbH+Kj$LC\#r;f565E;o`"=WSLBPlZ*;m^dPC(\:4l_>cQGXi?ZI1"2u3JMXO,HB);7ZJW0Y'4;BAtA95/_.sZ3"LUh,l`&,hpRoUKM*_N_M7SUPW`b,OCjcGeG1K-m(Q]@Y3LguaqRX8fVL9bq@RUE$DZOddJ4D%8I'_rIAQFIa.;WEuiFIen`n3Ogn/]2!Emb4t6?nGo=;j$!bdG2Bprq>OP0;$QC_lpta?dIXjoX\>8kSY_q0$ITH(;=uuC$6HbJ'dIFka>r)%upCY0gAoQ^8\&Ge&D),"K=ZuKCXX+qUOW"=e0f-lE&)Ld#cl+oafXbAp!4A+aKEc?jeG%3lg@uXuYQ,';k,^Hd%3io%1RKA%P'%aIUf@endstream +endobj +22 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2109 +>> +stream +Gatm?#($0T^&]5`%[E"sCu2'7>J"rmXR8sQj0QO58\u^um9,e"A!Cs^=@0QjV_%+s^+@B9WPDEKdX4LT'=/7&L%mm+Kr.>=!gt=QAYoH*n!]]5bPTa1pEO'IhO"skJ01>ocQht-F&N[2rQL/g$lK-O7=74[W3?;]8%d?CQ5%\T^sE(JgH8FOUY^VoUCI5p`ei'XR+2rX5+da`:?aee,SK3e!m@338OSe7-:K885D;_%.BF_>9?uI-9*-/M+`4.rZs]!9U*4feT8,O\$:/EhqZthH7*?l,+^%%qdkgkZ-qp5Ku7fA5908i]FH)Bj.3@[RN"a#J"fZe--4ADS_rMEiZE@I=.o!57G2d#/"/U*fI5jc&$$3gb%L9K8o4brD@"OWK7sRV7GSC1E9g"S0(`5&rkb9/Y4&60p3N5*)(g/?j2B3B1:IGZt*fH_N(U*ArFRGSY6$7*1->32UU5!g'XIk01\';p_`65])JOI?fG`&:jlZ/r`O)\0lYICkoo]7-@"WIM.WnLY@5sg/nTtDOFRfU6[E9C#Y#^bSGmI)_Ic%lG]q12loDPf!f`,HF4t"l"m;[m$LPs51j6]Bp%

jp_;/k@4U).?'Z042[-@B*tB2<2H*o&T\F;-um"'t,*YTfuJUa7(R,2q\(P$Zl_:sF:lQdPhN2X3#jOlTdaY8NH;*c`DRee;=k"f7TVH>R6[tTM@"ipdhJI+jED(DCTLR".V^Jl$(>r1Kt;PTG##X):c:fhg4N6Z?0,e'nB^[PmEKL4P9=!_AX"gdF&d[SMIp>Yi&9:#:9Ig@>N[3ger\n8:7,;>1Y&X1a9s!bm/rPSU71r"'-CQ=W34iDDo_P^`C&EF+_Q?RutaeLBSfS41-`3%]dOaU2M>_AdY(dEfF9e-7F_,gNDT'sPEPqk7XjCKnfUPN&KR>89#NF>+P2crB$Mp,%D)**:jsLH'D)]j?H]n[-r\0*1ACmL?Wq]+2`#.@V*bd-RsfR_7dnA6p6*UFNPE2A+]8%>l:f>$Tbnc)[+9bV;cC$m%pq8trYBd`#/GJ'BReSL\+aGr5&9MSk=M=N2!WM4E`F>lSUjh6XP[dZI4PR)',mpfg#cfQg\rFs_*jeKI%5LTI5FZ-N$"e6c@XQpX3'ScW.R!N??[s,Z9^0P1\J]9\2c.r//atK4A.Gp_^7l.*Rih;BWGe4O[j/hV>eKN=_2nspZCWrMcUtS9&)g*%C&~>endstream +endobj +23 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1821 +>> +stream +Gau0CgN)"=&:O:SF=EJ1cH7no`5/6o+GjC'NO.qFn@g#;24tP?-&iUQPcTf4ms@M?DN^33=X]cE4EJ+2FSG%9VCp_KnTti[]q*NhND4SW-9g*9Xd:lTVJa"9"92l`thS^$=+@+,#:N;0KIBj5aseT6,/P!;A-%0Qqb3!mF'iCHS_u/FSoV*=m11K2^0f.QH%DV,m$f"(DDo?-.#[>[%$>t:CCRVueLP"JbFC\E0T;8%AjCc!;>\jgHmhm>DUB+CO$2Jb<(R)3(%`2](AjN+')RFA-:-rSZXA&ZnA$N\RAPiQ7mI\&@Wm[cD/%!Wsp,&dq\9e*YB?5rQDH)Qr"Z*HAHbhAg>2LjMNdX1]s2hQKIkF1[?QGbiWGOKI1_?b4K,(qq^&uJ^\6`cdKmJ+l48\T2fk-fUWA-l%#`23?+B2!i%j=H2;NKnbf1&&.6Wm-+8!l'>=OIXc0NG::UN$[=L=d8Bq2jd=VZ"/g60s.Hto[>H7F:QdDmjue?\ppjXAU+.@[+8]uYCiEXgNG[&j*mN(LRQU.+,5N#d";rH?m*5-Y0(9elEd@ioGs\,EdZ^8+oN(#6$7af,!$WDUi!;.g#Wf(i-:6,tY28&UcA#&_61",>I&99(bShG+">K]AdITtOVGlNX%Zga'C^anb)]E%SH#7J:rJ.N\AbhD%TVj2+7;K.94Q;"Bt#I9MlsL@Li]QdJGMA)rRr76P+d/7c8.:r*FDc.bIAo$Th:8&A@/_)&ac-l+RA'/-6HAeSo0BVVo[cXW,L'O/D8nX-qLEZFug?rXUFCioC)"k\)TREIPUmZ7Y04J/fNZY$(&1mlS$lAml,)8=n0#PeXr"\ZM@C:"E9a+H-L!=4B@cqf"lWlJV>Fd$`s3Es4eE5TD.#$s;&qZg'NhM>Ns&%!?`(&i2Vendstream +endobj +xref +0 24 +0000000000 65535 f +0000000061 00000 n +0000000112 00000 n +0000000219 00000 n +0000000331 00000 n +0000000436 00000 n +0000000641 00000 n +0000000846 00000 n +0000001051 00000 n +0000001256 00000 n +0000001461 00000 n +0000001667 00000 n +0000001873 00000 n +0000002079 00000 n +0000002149 00000 n +0000002452 00000 n +0000002557 00000 n +0000005066 00000 n +0000007222 00000 n +0000009694 00000 n +0000010916 00000 n +0000013047 00000 n +0000015193 00000 n +0000017394 00000 n +trailer +<< +/ID +[] +% ReportLab generated PDF document -- digest (opensource) + +/Info 14 0 R +/Root 13 0 R +/Size 24 +>> +startxref +19307 +%%EOF diff --git a/lab_rag/Lab2_Indeks_dan_Pencarian.pdf b/lab_rag/Lab2_Indeks_dan_Pencarian.pdf new file mode 100644 index 0000000..7f2569c --- /dev/null +++ b/lab_rag/Lab2_Indeks_dan_Pencarian.pdf @@ -0,0 +1,194 @@ +%PDF-1.4 +%東京 ReportLab Generated PDF document (opensource) +1 0 obj +<< +/F1 2 0 R /F2 3 0 R /F3 4 0 R +>> +endobj +2 0 obj +<< +/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font +>> +endobj +3 0 obj +<< +/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font +>> +endobj +4 0 obj +<< +/BaseFont /Courier /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font +>> +endobj +5 0 obj +<< +/Contents 15 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 14 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +6 0 obj +<< +/Contents 16 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 14 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +7 0 obj +<< +/Contents 17 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 14 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +8 0 obj +<< +/Contents 18 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 14 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +9 0 obj +<< +/Contents 19 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 14 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +10 0 obj +<< +/Contents 20 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 14 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +11 0 obj +<< +/Contents 21 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 14 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +12 0 obj +<< +/PageMode /UseNone /Pages 14 0 R /Type /Catalog +>> +endobj +13 0 obj +<< +/Author (\(anonymous\)) /CreationDate (D:20261102110223+07'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20261102110223+07'00') /Producer (ReportLab PDF Library - \(opensource\)) + /Subject (\(unspecified\)) /Title (Lab 2 - Bangun Indeks & Cari) /Trapped /False +>> +endobj +14 0 obj +<< +/Count 7 /Kids [ 5 0 R 6 0 R 7 0 R 8 0 R 9 0 R 10 0 R 11 0 R ] /Type /Pages +>> +endobj +15 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2467 +>> +stream +Gb"/(D/\/e&H:NnEPTr;/Rh`0S#$P4ODIRV/HO;>^qKpWBT'<5]m5jl,/A[*Nmt+>bL3c"=L"U!-1U)AG:6"0i;$*Pm0p#Hjhno_G9;u?;cuF?\=#jAa%T^.R_pg6`.[Q[d5q^M9b=s#_3)8)O+Sj)H89[>cQY3OqbCIS23Q)=2L5k>B@SUU>Rk;l8p[%51(4)\c/ZECA;flE[%d4+Q#.H-e'Q3!SNI-"sFBQZO?e0Pc*Yj):#O[&RJcuh;Vr2Vu-)&WfpdpQ;/:OA14j,g2B>m4B&OT&7,!ZZVo-d"DPp<3s'0Yecd^G\>Y'T2I5's$XZ(,GF?okH&gZX#TZU$9I^"tR4q,XP[<3HX^i9XAP0rfY`j.mAp51(`ZBPXM+L4dOjrYs:8BmHl9C%C0k&5NeSPK,a#Y??ej+Fa6R/Xc*BMQ`@,c"O3Gr)Kq7,?M2*k$Pq_'E?9&i5f.D[hfc-ZGgj'HNL'm_g(I;\:UdPMYs3piZs27@>8##@,rOXq`[-WSl6?K@Fi4XI,b<")lDhA5NdflhWF6D"=G-F#b[Zrs4,XN`R#U&04ckaBNE_tjPrjpn%+fgsB\$mi9f,6E`#+(?%Mu\e'%&/^7HQ7En6"@hKU^F>SToCD/c4usl9fPjC.EEeJ_Y]Q+)fC7q(@m:k6*^5`dqaMZaV0ulInpUqtAV.Tp^o/#?&AbAD9!3)ne0=7U#UUHZsl"Ss4&7M/KDIVU.\='`=E<.GKD'Q"QJT[tl@hB/2Kt*n[ccVc36r(YA6?jT:Y%Fd=,,qnCT[cS&A:T,]IO``IQ0Z)V-N)%/=h6uE3aN2=ETTf?405.ti7;?imj5"@#EgK90hBIbn,e*]kq.NU1T7snr;((m8naHdZ]=<,:\@[Jqh?e]r[YLjU!Fhe#[f!j/lpe5rH;hEBs,O):C#%)pA=aLguA^t//Z7k6@8>&huGfCAI@'];M2I\n2hdFbD,V+[qHo`G\CYVoZ:HXXOMbgrhFB/%YnYu%,AoIUV&)IO:a,tNTMoX;Z[kekdKkF5LW%oGc?388+)3DjFLQd23k#[h?u_9SN%(_/VJa>sR0(VAd>cF/E+J7FlPMZtBZ+0Ps^=Vd?N\!1=$riP?Nr*fPT&Po$7)"G"I(RtR+KLWmCK=:aX-6\r"V#&//G=fZ2d,1Nsm'_PHYB$95-el$GRV3&V7-*&Y*gV(PuetE$]^8m%bk6CcF]l[&3^:);?e"V8]Wf/&ahRL>r$pK3/YV`p/c"uPoBQbW.AOPU9W$5%D$ESmo"celK7B\U<`_W&WqumGr(1DO;?J!(HGO0U,oP%h6?s2rXXtnF%L]BuV@L@EB4f96PU%KSE-F1QY[lE#Ig2?OeFoPO$EHLKAN$Fd;]YK_XYk"(M:gjIkO^ZZ`,Q_JV4*"d"=tL3[e=-]u'[<>^W;c1jb7Qgp,1i),`3hH+ooYpu*Jq,o/>\2l_dJ=(25%3^^m*,':]ra.&ODQ*k6V`arnTcHc^+p;K:$qkkQ/FT^=ncq'P6qPV;;M!.d"lR@lP=[-`~>endstream +endobj +16 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2529 +>> +stream +Gb"/)gN)%<&q/A5FO`QW:/MRB,67TaV5tlEeoo2U\8SNJ%>c5g_MuB#.K04:*e5AD)$EAsM7fleM$21XT%f\$F(T+6(k8F^S0p]h:$M;e,h&LPJkX4(B_m:/Sf[iZe6%)V"NI6_DRa14R$dO=GJ<,Sbf79Vq1]W/51ufAqPHj5KT?'Y@ZcJ2XOf;BVWeWXmT3ApH"g_*PJ@N!niYZWdf9jD.H!nR!l#h:[J=\B`\]DTY4_G(,1GUgFO0,F*1s>:WNr8b7ck(YQ7?0"4uV*K.54J$*M(oY@`0)R/6^60OJtMfZV\Y@a=J)W8n>M"lKJ2rc=5h)!#S$nl2D5]gO_?5-d,&B]#.'sM;TF=h"-sC8;.b0,g!=7UY&f7->YJhkSNJsq6d7C&6B.5Wg$'YBA5_a0MdRO"qDssIk/\3p'H5q9&rR0Wc(8ohtXtSA\aqq*J$BRdG]GoL@Ng'1&[u/j/la;kMc22_6umq)cOXdCXfg4UXubqgW-bSI7<$NQ+=O5FC"aC>Es,@'XP'Tlrm+Jck'^Yk.5?;CfdBbm@3FDrRX5Zm08c??@TT&,j=ad#A\i0:m"UXj`E)A*!9tY=(7k'J-JiKefk_6_6HDJAH_9,?&,pQ"G1-+7EUNRGS(5]lN4nB#J&Mt"G1pl$&]?4+r9FnHT@EQEo@e>l.&RuKP4]CTC*dM'_Y1VLMMTN`/Rr8XcTYX"h(T_Y=^eVPtsaM.)`*dbgJ$ske4&SM/%h(>V^Rl8sQAZ_`#qEYu"-7Eobtq6it9($<9o_cNplf9-8e`3c74GR%M1q_4nDT64EedV\L1er,c-$+_Z6iQ*;>O%i5Sa>9[]42@'-[6RYT(Xq@41dWMr3aHJF,2(jD!WE!RT_>;o[aJF^.b!u&6%4,:@(FG=3RR.C?6X;VGV`ac5/W.kf>K3U$+IKdnHAID&noK*]n?GGej5q(Ae5I8qUqQ/:+A3pVX],a*:n[c`HZV+fCNKiTS))rg3/KHjW6*mF.%jR4oMOO!(1fnJ.#kC53Kt=mQZJMNRK5?1c707qY!*henX:Y[p[,DP2L9l#WWX?/i4(/1mAdM]V*0j0)^GsW5*2-^b_r!'a&FO`a)q]`?aCBih>ROFu7=&=#WY4!ifu*"Ro'CB-H!iYKbPAu44SV.(#JT@`V*'!)!pjQSchA\NpMWHB#OB(VO1^CO42u"#@hXK^N("1%m@^`;Ub/BSE\gGf\bqVn`?/PYVP-0B%Z%7p/j#dMjcbB?l+P/(HF^Hc3["R"j((0SC&8n#J`f1i3d;JYLXk[reH_cE1W?u6aGhZ$=JlpT`Ajn!MR45#O<^#V?]O;!Ht-@:Qe*6_je82Y>QRD--sCq&PoZTCp?o4M:OlgOrBR?UDNM?`c@$43OfYU.ZQ@!.H5JX!H>X)+Es;a-@hceP]79AkotgC3IIa*Cr]5I83VMkc"j=1VNte)np):+$e@^k,1$@7L1ga6s`/"6d;2LY1RM=>nX3R]f`fg'm7/E3FTUJq?`=Pm`QDM5Gd_<%4N,;bE,;mts^XY4P\),P*iV8$hCg4.ormWi#Vfb08a[IBIW82S$CH)31%c2IW3^^bG6i,Raiq'\);''X1+V!WUUSsh>MlMG[4E7N9!XV=<(;Ac#$>Q=ma5KIc[Z]aqE@S"o`*Zj"9gR6dPKWQU4U0HgB/mW;QV*`,NtcAo!T*gM+QBIk#KYQ4Z6Zef"c(X*&GrG1pp$qH#Z$0/+TdjJfK/`$/43KH)u&pb/$[iSD.Fm$=Vpe3oReLdAdbZ0Kr1%0-lSqNMfPSV?kHF]O2gO^VV1m;0&`>K3l?DuHa9"kb$b0r0FsBnnUIZ#lZ=>LDV]s89$P8"3$Ah;(KUH#u93h^a2;%J8ds':d6]P&5X#EFt[eO#n;MbH~>endstream +endobj +17 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1877 +>> +stream +Gatm;D0+Gi%/ui*J]hqDVruF$Cs."uU":kh\$ao;ebbZE*,X(Y,Djhs0tmM^!S"0@3pF4&(F^V#4910BKK+5ObM@6'!rTEWnJ);s_eKR,b,2E>!5GU1r]-r($PG!n:sZJ9a-Qg^_mbJ9"0]-0o*+`Po*%fIisX.@Q,<#lObctMR%2"X*`fI8h+%T_2?c8PQN!&b*:4#t_%I2F0jE4"#B*#[\1a5T),(j:/SB%jcbW0)^,keScH7QuTBH.D>OP`lR.1N]^P0-oo#^OoPn+7U+Vc'35JZbXRSr?>+nV?fI>@T>cK;HO"o)5bpj69CK[8K]+U8b7Dt/upuFi,\J'8cZ_!Y,Z>-Dr>-ECTW1NN?@;iL(TD&hhT<@?UmS^*Kf:sD>KQB2Y>$d9dnn!@ADT$G>PLfTC:3@)YV84?ZJCUKUiUiQESdS)o-7#f24&H9>"VNsB`iQ"6E%aD52)=BX-?6dN$<0#,7BCUdWsLe(gkc.@jO3J@klpj+f4)'b>2F[h_J#d@4&gWP.:qA]YWU_?i5=rdLbf,Sjl>a]n[d=A_@P?kr-2`42D_<\9,ZRl,E>0(11PHC-89*#L0mmrq65$j/IPun@s"Hd-:%R'a)Nhc877-*,:\6eCoB)nn)"'&L6lYe[=ua[ggJ&Oh,3ic-]Tug8e#X!!.V68QEjHnK,K<,d'tBBobADIe<5Vcm;RI?:??Z/;;h]QkI5*nkCYTqF-e=<]gQ(kkV>R2V)O/CVJdmQMGDOn2/5`[*PtW\j`+G/GK;CJ$B&I"=(4e).1K<9_P;o#;5gUSnO]Q-2_n>HgfTdrb)AXiKnY@%'plrH[nWCQ(3\hZhL*S#@)>MDj'+lZC0GF`c+L8LX.o[c=8+*Y\l*Gj,;:e`;4fW*9O>7uuK[9@cW`M9?-/j%A6O]XP*(,[OgP6r(<=S5_P\[_/L:TcR7r[bo]',HnOF'QSkLFq[Lh_P$bF(spsXe>62WA"t^DHIT[^%`TIbcGksiC(,(pJ*`5p3kK-c^m$rB,fWhk(UUtp`Ab[IO(GAG3IPZML"BRD%:8`2l,%tJ;bLJ;/l]CI^"]h7AJD$,SpPN>3cMsT+K]OJ(+6M9K=<:o.:5'g35@`jBr";FT!s"]0,VNnhJE+/t(smk^0^!dR@"C2b[R!naM@Nk3E^A\m4nKT7Ul$8m)_qQg!5_QT!4C*4#$*T6!cbE[_,~>endstream +endobj +18 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2130 +>> +stream +GatmD3>!'kk#\TijYTQ`.nOfH<]ZMe>4;S4gM;#H:5Z'#pNpBP_%??El%fCOGA$(*m*+5I\CA?U>J-#,U6>U@3HrU4dU5E0;s,S=H?;&io]=J0k(kCFSV+nkZeob`%p[id1fH;O(Z)cZ7o&gRn;-dCa$"HK)T:-O,9d^-9i#tHE'o7Bf\PEjZnsi-3X<^]A![]"%imVm#!bk+MWq/@%`=0TY7&P_YhN`:Xe(>IAV>M%@1l+g`2MuP*QTr+a205PSQB8b)#[j'K-0K%o\Zg1S0TEsf#loC(f>qJi2GZe&FIl=;^Ct5bZV!oB_96!]!P*X6;MYs,pN2V(_[?_h0k0WXh228=/Y3q.%2DY+:SKGR)A8^Rr4%'FFJ-h0hG(!6sKK;7VY=A=+N,ID#MQ^8T$&6$?IR0G313DTk&n[:)dT`+]rFjb@,0H+@[5u%U6Zn7IU,k*WE%X0DY[*B!Br$6E_B1Xu'Tk?$6.\GC%j7:Z&qaG]@o[VGYaerj(pK-E3Y&nNNJjMdHV"!qGg:a1d<_mm!B9HeoJW\Xa6(hf7HM8siQGI,O[GY4EJ%\Pd7's/tQT]5$lB7D3F01NgBCF'[J9@g_Z1kX2#;0\9f'F7.X=?N9&@U@a3m0L=!S1#1_OaPWOIYOC-'V;K+OmRd#'TR*`ej9Fam("p%NVm^mc<39WsWmBn4Y81e*m$E^jB"cG]%E(;aOP&bMlp%l-\M?\IA=KX*Ta\'ds7[>JB85(ae)UR:]>_QVWHKRbR%&m!7l0Xu6BE/ds;g>(Vb&X)UtN%ZS_S`+13k\7nH3#1sSQs,$D/h\*pX$khl&Vq`!$2c82+NVJ1P*G&R\_S[C:fU%!`"h0u;_SjAWnuK6*%)(P2.ndCHoo8=MbGk2/#."Xlbf+$l^4jDMr3iIkP^S-*j#;JQ4UhP6]smrbaIBi6=H5*J@]([<1.$JM*cA&9[?/+$>m\O0G>%AO%e/C%4h"NgeZ`Q2D)tJ'=8]'*O%)!M$L2Uk.S[po6&Hd>h/`qfLi(DH.-IiI'OR:Z=LpSO5jeaLeEOkAd)V&E8\ZY7/d+H2Cn&"5to]Ufq^X>W@mWAG=V(n@I?D=RR@Nge#p!u&9!k$3IgB>q>"iWOlEVeia_/?K%i/iL^%b'd:=*27JE89>Y)<'DKsHlT_,ZbHVu7J)Wgjr_)/aPbTg`"9#V(P*^bD"Mi`^r3E(Un+hb?CALG6nE=Ud7\e>QW78)oMMI]7885#+*SdlM(sTnNesDl:JN#ms1o3es%CW>oPb&]d1qA6b4%p&~>endstream +endobj +19 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1734 +>> +stream +Gatm;D,8nW&H9tY(qFj*BN$jEnuB#k3An2-.*[HBknNA']d9$E_XA@#>:$G%#V'_`)E"%rtW"*U^In-[R65E8^/V*$-15^n%+p\VROR7:Sa<`uK:a+uYe+L)(T,7gbIb6O<'e^;HBC`3["@+Af1iP4On3Xr<<'?m&X>U/0cHS#KpkT](9qaEHl).@Y.:66L3XqM.MIK9hO!O\YSpV$^^qZR^reo#:b<4o+tO?5o-,h3QjSiKqcM'Q![1"E&?4/=LFM@`'?nI$iBkP_8kdK,A!-tsGSqbt7B0l6\tpVV@bkn"@!)0)L,AV+ioXa9WEpU'0Hl*u'N!$S\>S228SNaE=%C,S(a!mPhi2217`F%H!Ml*$[h0S'C.@ST5),"]LQTLniRa9Z68edjolJ)*M-o=IFZjD#0G'Wb`]O$8">+N""je&q>D[h&J:PfS@k!m57s5F%&^OFWJ2P8t+8D(F"?23mo89]/(d()d+frZ[T>#N$F)a_g8+#h`50r#m3Es^lHE=`[kpB(CQp'WcF#FZXB99]MrsQe!MkR/Ndcf=G;^LaSG;sFQUI]KeH(cAs#3Q/iXT@ppM*sU"93OoEB?%eT'e(HH#b+-3U=;:WRO6s/Kf@a[iP\D^-T]FbRg<2YCbqnQ7WLV3=MPf@mOdBaHto@rk4+ABP9XU8-DYRNsh&m+_*GB#dUr`kX7BO,5Mg'+&uh_;f<@P&PQ,,i*+`jo9.N=\*m1gP'qEn4b?]ZiG2C+NoE+P9_#8S[+HBo[BfdBDKas*$cFa^4XK$^i2W4e%O+cZ"G?[lJ\KM[M!^m8Au5qb)cEDY>OX7h&U$Ok-(_Uhbep)Y0(GM^d\$ou(7iVmM`c70PA\GDFrVT1T.%&1)D`&d3d'E_ErR."Uje@>`!2nU'b'm>i_j]leelNh9.]e5=D+$_Z0J72n8)FgE\t@WEjlV$^5E3OCU;63]omth?`]TP'p%(]\8)t=FDLHbWg1l;*]:^3!gNflc7qk,3`akurb;fi3cV&,JEt4a1ek%Zq?D`9K6Sl"h,PLo;HT(4#-N0!#j2Npo=X<+@KOj%JtZ^$Tu`qm\+d&S5`JjLZ)*ebD7be%Wj^9R:mf#(pNdd=Z[>X62:SJ"hftfe`)4t^luk$25Q1#CHT((oXo-JK5Fl3FDbJFNec~>endstream +endobj +20 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2205 +>> +stream +Gat=,D0+E#&H;*)Z(jtt>g',NnJ`pJELXJ_,i`kWqOrNYk!/uYT`aVWBhJ0hIJ-DKOq,B(#J6BNObHS6R_FJcKJopsLlf`bjoJ[nF?Q87VqUM^`OnOb@Q;_]!nok?D.+fI9>Vq<8/d`c'EA)Rdc,mC91UU6QVKUYl5UHO[8'q1@o'*h,>%ht$t1\SK?kAZP,j80j:_16<)'^;HL4;UBg]b40li;DpM1.3qIC09I!SE&q_oVShYhmZ\@EPm)^t5^&J09j`isdc,30_N('q`;&9?Z]Fl^^Kef#H(O#HO4p"1/lHP^=iX^tZ-'t9FqXg*LZaEU"KGgUm%$,hEV'a:"E_f93/DCRR;ka^41PR.(R#khZ`W*-gt+BB#GScif+mCWCc"FFSC?T0of[ETR&6mD+AGtW>[U9j=^_H,Uj:ft:TEnUO(BA?AYK?mY=NpEoiD39Z2_PC03H9drIe'O"@i]6CUrABm].*f(h[WC4tJWfJ/Cn`N#_(+_g`3@2sX\mF0cF-!%L(c4l9]pZD,/(aFlu,q@Q6QJN.8"!46](?QNVW]%0;>3(%lLnm#>0eB)HVG33]s*&T2]lsU5Mgd6;qntWK)4Uam_sVtQA88@&!45mSddX2*,MM^O,+:[Fu2&j++V=@*DK3e^re"hPmF\s6>IdB!@l-u7k2:X3O04NbSV)/@RUMu/UT-Ib9!77\=*_n.S@B#I!`>c?3@6CJhcKG7kc64I(3g*6uUna2V<$":K`um^bZi+"VC%fi1rG\;Oeig5_n\prKV=6i)P^\d9`>"Gq[m\^`eW:6j>i:]Rh`e`FF]))48S:25^I.7pO7$cm4RSISfR*$5)kG.+Em]X9jtV6pB$D#_WYQm[KHL#h&$tEc:PG$JG4.i1ptP76S7bP4g&W2ZSZkTL1UaS8j.W7@qNq,Zl:j#eYjmG),C&pHkqM[PC2@Es$;R"MS7SkbHrfSnUY`kQS.!jeR0qpp]'4<.Lq`dcor%=R_u*Mh*s+]qNeT*f/5]BV'5!@UosF)RBc>`nM9aV-Pc*)MYYJ2@I:A+XEiD/qR[)q,VO;<@\J,[*QBO.&pG"R0C]IX&@&u\8O=bQTLqRP3&no_=r)WI(SG<_-O@@Y6Y?)r741&o8Mm+CcV<(-Y@sM"[<\ZU-&O#ak(&;UqjQ/pin,47YHB89.NsD2;GE.gqV^L]qS6eW$FG.'$cD[*Wff`oC!*,]iCt#]?a,W=g+6L`1s4pRDfRENnYY5Q#mE^kquuGSc^D1C<$bg3go=N.S1RMcbQ@O#`X-Z1elh!FGJ#UgS:5#$EQ4:JrMWX^mrg]_F\Ys@pqKbn\67>#of0PHN34V$X1A[Wq;ubZ3imMQtmYjqf%]uB9]!NnSTMhGa>>2QQBC)Nu[@l3:bQdn9P73FT;3Gnrk"5rendstream +endobj +21 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1664 +>> +stream +GasaoD0)19&H;*)Z,97MPi@l,a-PNNFHY:JVGURJQRT_*3=P@M0J/ZI@%O]GQqu[aIe*/BqdiGC-L>2'ceaZ*ab:%Vcf1'FQs8n-jd927b;%Wr1WQ@!o+^hhGf!B3iGnqi-^_XpF2+KFG12/a/gf/f"FFT41cdpQ-ZZ#oiJ\`*3oJ-XtV_RC'E+)VP7VL2hJT4B)(dLWk[B0n4r&TPq`+Oo14ZNMg=K+D3Nee4Fjn/ZnpFdg^4V>PIc6EQ8`F:?>m/Rqn4q>B@RrN@.BZ>ZI.GRj%1ZVm9*'i33%Sf\[XV+OlBEO",&(2&55[`6O?B>AdSoF=\f+fqC@o6>Cg6R>QuM'A+D]]/JhW[Qd[:u[on#KR4u&1b`2AQiTg*RH?!c;C)8_UXk:d;Q&)MR"_+S:^b7MH^Ld;9C=jLuk%78W^d`RNfPWj?)X,=PAZ,dm8Wg=-mJV#!6m=eVF0MX$k^I?Ts=C&G6]'>gnSr+[$eSAN'BYia5FM<7RH.qXPUgg;P+Y0O#e4EG=70o[+G89sW:'ku;VYX)c/n6U72npk%c%lP626@$@'VNa!7f&&lm?'<9cM<8,_>`OX]FJfe9fe5!:G2(!M12-fD`<9^jM1:W0;>1^jm%2j"g[&j$1kd8:H*JfYr1gYL5,2%N/H'iY>R``CtBYM3iiSql!`&``q',9k8hYXAVU=EOa/8ccddGk[ID^]BWAS!E>dEIOh&Ndho2KgZ>_)&lPpS*>$..!PaTrFV7q>Vs$GYW8MGe0Z[O5941[B/X1>ZY-rcKWqZDhCEi@dNrQl&7_s#("6X"`$!#fJ3+X$nVfp"`efb&3)&J@?*(,&-^5U?FF&4&Up/3s:;Q`CogjgkHo+p'AFaB(bt&J_(H#Ul#[Z`o,?qbKBK^R`J%R3_H+^N2TbH1K0Y=8,ZqS`r0ul05a'&HDe2zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz!!!#7'`8:dFO<`7]gRb_%j((812514MJa0B.)!u_++@>>0B<;ugBjo]Xa9&j8%Ng,&fDQYS*eRr6_W&/goiEgHgeXgBh!BAgA/oF^N`Ye;l1E%3%38`XLSMFmIVDR%HP>>aH&KgY&rJe*-#Z]Y(n7Dj32bjQGdVVb`gBETP?.LCP=3#mi%E58W38MEO6k5r[S<6[jJJ4al=H-YSc(hKZr<5\FD&iMi`H.SGDVT7p/+_(@5jNK2l-G3raR'EA-#8?)0d42k!gHhQf?fWZMne+_aLs3Eq0CgWEjPI#Aqd^jSedcto:c7RRYH)[Hp=LN&!i]Hu3dn`3)CA6P.T9_rl"&"*O;o\a::<-[fm5=R$i\We=5CU7FJOZY:UIJnBSh3S[Oe7>)keV,bVG1#\a)InF!<@Y,Pi_b$68-3_ZI=XD-P@%)U8"AGqWO]K?N&BQ;r,$-$O@#_l`IY_jmM_\?=$sq^3uubGOOD->VSkd0"pmTWr2(UO2f/X;$^m_TY\R''.L*=X&6+!]kGll9s%U,.TNKJ]692$X:#R20S?=e#-!rlRZAT\6Z^ie0Ej='dn(g,,-;UB(#;;bsf>hu8d3/tm]hmEe,rhuEYIGO6A*A-c21L:Js@]m=hQY$J).X%$TCfk$LI;i`"bDCq\VS5t%2fk9,BCtZ*?/c,>0YH#cc_V+UH32BY#S9^e`l<]pY;O8^A@,qoTV+SWLDn.ofcZfAe"P`4?T,"Uh95;56UfL"+W%(+i_:;i6_+^]2#p4%mfDdF$>u5j-F`F"+"$6*!qVds08F:O.Sa;MmYcpopb`k:]e$0udcn$>`[:6XZ0qhRo7gI+;i7!]BqTkGkScU-5@OofPI*p_'/T\?u("hU0ijFNgQ;VULrkJ"8jTW)83(#ZO?QW+4ZXU8WREOkH\g3^WoJ!)T!ZI'Mmbi;WN3O-EXVba;h(XBW1%lDq+c<)C2Mm;_1+W>RuBq.Z"da7JH<.s/,tqqqE%^=(JhN!p5@LZ2-2V^U\)+Y?S'h#U=;ig42I,_Q&$g`fac8f;l35;EO5&e\#7Ae^A4Y>OMV4hSU*tf<48JD;^EedS=kC)Kqh/![T;(lF6C$iIV[i^g9k]Fk>3'u=4l6]=aY[!BrZ%)[P$[k.Z4':2CKiOP2+ht'rWOa>1FNLCe,G`jn+,L/?F4id(*7pCb.Scac[rN*O6P/C>(jS6C"MIlrW[P%@>DlglmSMU[4ZV9;KN(liMNoDcSTiqq?`lc)<3Pl_`ueN>7HN^CF6C.,!rr>r3:7Hb$f9uX3mq'.;T8J4F2N_A5s[dN\%6\Gd\B%rlT/e6o\PFor'1M>"g[;4B^1M?FMhnO9t;K]ad>Ah!j?B*5NW,:*)H,PLN<;?Fdhp[u0,upua3Qdq098.\a\ss+1mu^>62ANRdo?TYiBD[?E0/$+49C(rd*IEa82/?1mm$jQn8YOkljdS/YOch)2Jqg\VJOhb)@_DQ9PIa`4XiST)n`.[%gS70dqp`d((@"%Aq2T*?;-f7HJ0&GZ!oD!!)L_e9#']U9\%=;6*_Llfs*#qtF#0$=3?4[+'QcJ,%uXK7\\[2QNuD0%DP^W'1A"p[[IkS'rSI1=6OM2Q1CIgp-i]gqA&YHFeFqC6qYog!edaSntMs8t2FZp$^Mlms_KZh`dBj1>G!Ae3crHHi4ltn/#q*6?21[GkK`qslPI-np?t%fP+U:@r2pV$=XlhC.7I+>._7:H.m6fmK[rVF&`dQO"C36E:'YXD*KT8E44oKmoTNk/8(eZ)Uc$\#.qhr"J1l`[4-,0JP;rq+Z8HiA$mofcZd@YIIcHB200n=DUZU3#MCKm"I?3E>88f3bGR`F"n4@\c%9:q!`\@mWIo$H7t9ru[-f>cCUIl]M8@accVnk)0CMc*JMfBc;-or-@59JMb?p7-X8bro/."`:S*Ho][8OC=&7gIItqU^AI?E5Q=\)c)LNXg(t:kZ\Ma8&MN^]HAP^1IC8ibkK]WFs8D]\^]/cUEA$=\DXmTS5LUZ2DVUVNhL5.S4*KsMFm>4F7losURD-l8q/]F/=acZOcd.jJW+=\nEGFqjf$_.MNZGGU1htNr.eN,_\'TW+=P&!9F!CjTAE*D5Hf@:d-uFF1\!pa@(WVE5OI_q:iQD#$O]l(f8epZ5EZ2IA[;1-gEXE?KZO3H!&p0j6``!u$Wdg[DSaUiQDH[$'+Cho\:bQq82:iO'me25*/,4.WbNe2\T07RY&fY(TI\&N=@\NVN]eSSn^OlL>]_C90^]4;F\e+^n++A1^Cf1"rI-ZR6T)er-7KqmdMDWoI`p02Yep"_?YJ'XuFl]GKd\KHuDV_n7Dt_jsT;;dtZ*>A,%SlDOqgZqeU8%SbqX=6K2/?1$EiGfdCUEe(h.+_.q@3++S^e#fDQQ=>aNrIFIsn$TV&4[[oiLfXT_^EU1"U?B]Vhn;TYsB^YJ0jJQTG*Ap%'@lX6ZC[%j!=Poc*<`e"Dl:rH;h/%j)8i%&BgecCkmk^Oe*=g/mOeV2H^0ear_*q'^UL5YieFI\uiUeL,DR@MRn7(]go0)'`RW`J'`GNCg>fD`TmA!?,'fr-.Cs,9RR#jI]?B^SqPk=*dc,7Yj46tl!(^ZB+GsZgMai([B$IAb,&>`UHHZEl7:L>(ItIJnib+@\Gd?G!*gp^INC\#\=_N"A1eX&>%%>QpET]fs8-/L]QisUCT0I_c^Ql>YM]TsHhQgrE-GW5i<=S%qP5Vo/l"Q8\oaqKLKCj&F\aS>$bc>pMgg0UkN9a8:HRmmX(Ul(&%>R`V9R=#+i;.7BpJYopNsE-6M3g/*^/"Op&.1C*rG)hDsZ@'<8#:QlY4D"*E/B1[/'Opn%UOJZRkeJ6&Kq?]32[bAc$ZR($`O9Rl5,pmC(dIghng?_PI.n641^'r9X5-Hf@:d-rk_no*CWB?[:au67`!+dnd>:qu%0V5:7d)>#3[3g"^(enYl2]bO#G7pW+_SI%j63QeXfhn'n>#^%6;dF4L!i[r1#*eB?N0LAh)Fhl6R'J%mRr]"MOaG3qn<\L6?Z_hJVL"lK/u\MB\V>@.-Y_Zo;cjj>69hJW$k517QV3p#uZ5:7^%ppkg6=FJ0+PPhL7gW'1N!!'g/N;6Vq%$t`cLbWDZfRKGpKq-Pc7is^0i5h$*1M=uA$k2bY\.ca7\T;IsVodHf72qSS[FGLGFm@J]htO+;h5OVfXqfpZjj\d,B?cmA9%<%_1rW[+5!"/j\;HFB(Sr[V^6<,6hb,CeIsl6C3DrTb.3'`AC,JP7F'OcbbY^I^^Y5VJf`,-ltGHH!:-f@&?'HKod)p3`)fEM+ZnQ(P#VoQIPG>rk2MQN>%C`7T"]Dh6'm/hehGuR%ETqlDID%/6\Dl+IJ$fWA\UWGo_hZcrmcmCc7CR0jr!I=5mIG8kNZC2dmU'%)\0^=:bEf)8X%q'^FVe/Oc3mtQ[A55muI8;MQj=hRr?%:em!&m+)4Y:\#2)@B@3GX$D7V5)`C[QR'XQko&\'F'[sX9lN%(l>^lM1'Znipmd;l=M-DKp.9!+N/jO!,.TNLUrX8%ArMnW&cR[A1#UO-KE%7P]W+1bC5%R@oV(GlXTX^JSP&f5eQdL[f;,L@,^A-=KVbj%_8XAY?DooD$e&EHKe6]1:IJ``?pHU:&Np%p0R'H5L45S3!;pQqQE&bSLF[#lCmH;MA!mbCs5JPJ[6*RF?K7?9sl6O+CLW`?+$d9!fKZ_"0MrE]=O6UjI3cj"3^W)`+6O']f=58EIq#1d*2^AdtE1'ZF,GOODRS"Z&TXek;pU6ep4Gh>*MqF=hlUMb0F26XRQRc8f]L!C.XJ]7Im"2,r/O8Db/FR7YB\qh?,N'q<=eqtN'gWr+a>lC#Pat'Zkp9\SbWjKO5;W:>of\d9(pjbEMYM^K]1h>Z%ZFB+K:\++t++L@%AQN/[(%$hRlEU32Bo2XG50BkYMF)=I5L]3*!_eMCj`<)Z[LnOus(c-:[tO[gf7cpUQ'Bl8((aW!C>64.`^0Z[4'E^9s^/Zr!j[r9h2c.&'Nc;mN698XY@NmAsHsMSF5'@e&Hs1a>r=W)Ss%aL0>D?%c:Fr*Z\P=BT`YZk=fYB#QI)&^fWer:fDVWoZsU1ml9@@aDNe6j45RYtGP=NV=0?AnZmhOYddFVm4[FK[>iH:d=M%?@ST5`.L'EZ!g&3,geZ2c8Buto?_s$1FUQ7Sg[.>qU\3L/G^3t@^%db9Z+J&70h-9*pkiaj%SJ>=0(Jr>N1O&DrEY7[ZX[7d]qisntL>.UiGFkN"+PIMM"DAn!T;DD_DGOTUP6PAFG\^-+Vf&4"?g8ElNM>jU;.t=?N06pZX&lK"UHl$Uem!('pLg2EULTshm7r96!!"L5_hScO'ORb5*D4LDeY26Urf^GqVpIF3(eF8\c"kn3l#PU6!+\'N&gN+;dU!Cm6upmbGPV.5(]$E&!!%P,@)n9JQX"Q&jiWk/N>q'O0DKVOcFro%>:j$c(c5o&3PM5Ho\p7Wqe"'C4.!Q&jbs0ESj.]g1,@;>f2$p8Eq&#'d*PVTbMW@#!;(6g^k!GB\:Hu#^V>9ik088ImQFsnJ;tX3&&7n]J)\iM)^KR:K8z5ae958%FXA>5AB%_mrtPz!6PF2SMnjFz!!5Eadg!B%z5QD(4g-A^Az#QUPn)sD#:z!?fm+"'l?9!!!!A!/*CMTW8(n!!!!%J5E-QF>X$u!!%NL&F-WRXp+k+!!!Q16Cg$]eGoRL!!!'cW7(s^)?9a;!'gMiFkT)^!rr<$!!iRu:)iD3z!!+4lB`hWMz+97'UD4mp1z"Fs=H%%_rdS%R25CWP*nDV9#euT`)(=oa#a"P4*d\Xg<'eTl+,uK]Dqm-!s/Pl^AI=*hZk8-KK+nV2Ad`ufe1X&a)QJ,r[SRZX'sCM&"W4F[3QMUT1]n#iV?"'HbrB`hWM!!!"`*Dc6I8kM^X>.#tf\6tTWFk9o-@:9kel1(o^]4_TDkKgW'rq>)b<:]hEO&oGaJLD)p["5@a!!!#AN[OY5@Ddg_HM"G.]^WcG[+OTZ?s'mB]l-eZ)W=2Jjq:]g*\GFkT)^!rr<$A]L#4*"WZ8@`/P!abC6DBWZL8H&!G:R50I;s8Moap'TDXHYp*$bpoC"5Tg>Tg-A^A!!!"1#G43_FqErGJZ]1W!!(.OY($ZBpd1q6[Vac_:HmIDGOO7nC\nk)q7=V,*?."ZAA*<^JqJ^?n#0*YNZULR>r-l%WrW2#J;V@1r7nc"?^LY.$m.[g])TdZhgSenrAUTIR8RIq#,:U@:tMaL0>G9^iJL-c*2+$JWZN#nQ^XA3R$^F*0>$SVUIUAkd0sCGC&e56TVHRe'hgb\)<&/^f?n[u-$XF2A!!#tmefH4*Q/A\`ZGB*#T;!0RWY7QCS(P`7I>HkP:OkAEhna*#sA$n6r@O2`EZV3]\rKd,dp4T&=Bi%0-A.PV8A0HE!MU.Pn]tkDKLF@,?1lSMb03#R_%+d%S>n?[Uh<[ISKLoD.RAG:ERMK+FoNQ5773j_iF-FIShe5IN5/)6/_&bVK)blO5hTRAShe5IN5/)6/_&bYFT;CA5hTRAShe5IN5/)6/_#(9q^M629#9toz(Qk>PT7%Yc$["o"kIGZs2JU`Tgph@t6M:63IJWT@I_U6jaH?8rD?'Y:J3A2#&GIj[0Ca`m[qaHneplZImnWu:H:j)pSOo"l\Hh.>7ukO.a&>"smFSQ!'j"X+NtW-=NZL@K75K=bWrW2#p^$6.;hhf;&U9-cKY!LVHHE>rXNQt=c-HM]jnnM]^M_l=_83t[GN?i-a,_>:Xr4t#eGoRLHj'0(.7;n.#eU;6:)iD3!!!".?r*@L`'''p9+^BqJZ]1W!$DL>j=*IO_[*mXThZQjC&e56@UN!'1;l>7^e57(["5@a!!",Gp>dYigqsE1"JJR0k\:(t!+K>3She5IN5/'tlEl,F"onWG#57+,6eoQb]EFp')sD#:!!$J9:S'>[4cI0L&F-WRXp+k++9qQ#.7;n.#eU;6:)iD3!!!".?r*@L`'''p9+^BqJZ]1W!$DL>j=*IO_[*mXThZQjC&e56@UN!'1;l>7^e57(["5@a!!",Gp>dYigqsE1"JJR0k\:(t!+K>3She5IN5/'tlEl,F"onWG#57+,6eoQb]EFp')sD#:!!$J9:S'>[4cI0L&F-WRXp+k++9qQ#.7;n.#eU;6:)iD3!!!".?r*@L`'''p9+^BqJZ]1W!$DL>j=*IO_[*mXThZQjC&e56@UN!'1;l>7^e57(["5@a!4\,[Rlb6+R+U'Dd*U.8Uni/!eeM-ZK+C00fWeqG)Dr]`,?qQj[-o\<3LLq,g9dj+RO_F?nFuZqgU?M)\T?rYS(GB&H]#kMB?sUOZa-lCq)^04[L:B[#Qn^rkc,n(aO,p1Q?"i>;h7?m4aX+L.\a&FiF6BKBe##hIXdkrQ?):..>,tTo>\%HP11>:$s0>Cc+%0jTXHh*CEmU66)Jl&?SF>X'6:=lXSRl"hg03Q&=4ltOc.p';`*]nNr/XeA%_O`o;Ier<,.9!*?p3u>0[gLr3c^m9M=0?r9e>Wdh2ZO#c-VkW>*_,'6#^+id8&E$HWYl/p+:Ek007Ce5UpIJ+^drYct@nbEj$VfqV&u"pYB3jU,]Y!.VhV4Cs=q(kJ"re7f"j%03UG(Dk\u7h9r<<`TuIj35_@pWD[ESXVkh(.oraMW-/8>!.4:$+mrbA?@l"O%GaT[2ArPp>dYigqsE1"JJR0k\:*JSb2PrQht\pSN=1*qemH:G`^(gNZDmg*&1n*'kV)kgC'oTT2(*4I.BkJ2&cN!Hh*CEmU66)Jl&?SF>X'6cKCgLDSQ3mDJj@0L(17hdd>l&GPCO]lLF]AkGqU`G1gGn=e@UE5(1";SN;`L2g3kde##k*eZ5%/Tj,paic-n$;bA'q#>D;2Lq`ufg/Z!,YN6O-687^e57(["5@a!!",Gp>dYigqsE1"JJR0k\:(t!+K>3She5IN5/'tlEl,F"onWG#57+,6eoQb]EFp')sD#:!!$J9:S'>[4cI0L&F-WRXp2[\fOn)"iZ:R^$$N5g&GIj[00uPc#.b]Q_dT0/AVb[MJL9$?-:?S+#eU;6:)iD3!"=X2-C#bB@0E$,GFAq[%jUQVKKaUn2#!\Zjjed#mk=uYi.Ca4B%@O#69#LGlX'1G,NFnbLg7#/iu60l:eu`]"3Ckr]rh9l07Gj(+i-R:8Z($2JjqNk)'m(r;HTK[V\*MmbE*Zk-]-bhTsMdp?^I5KnTmN;G!KEI@bfR\_D&;SK:S!5$cch!+1D--C#bB@0E$,GFArFN#cNqZK!1'c3/NgX1*!&9(/;g1M3S`3B9+inaZ8./@9H,DVZqUj:XK]<_q&44%GR*2JoIcAnPc*g$XhYhItF]3,i8MGkeORa!u*?J5='HPKFI20EOtQ4&(J%%if3HEkrPYSK[bp=(c&S"9o(%4F,@)R5Sn#]heCigZMnRFmIV8M2fu;aq4;$!_om\9nr9N*+nJV_&#G/+o"B*dogGKcCO>K]6*3HHN)2:^UAhlhR7Yd!64QWm,O^%YiZPIdh.*?EtNJ,bC>3<0kX#993<)&e^@jP13E;5-"ilYg9+#`''&E'C8JX+oMLuRCZYmKhuCf^MoZ/8NA1il$[qdM*<,&fVcOFQh'R#7c!aijs9uDReY[RPelDKqb<9\om?4p=jM4f*5UGlLa^jQZ)OlSN=1*DtP/6G`^(gNZDmg*&1n*("-L;j&N-\\U:IPZd1h1')+Js"&N=.c_N>74cDW>lqW`fr<%hC\m4`Y:m[B0e##hY)Gj&OWMujg8P/P63]];P/$&F[1G^hdVRghn^OH.FYI]DDj]p"sI%dT*s86s8>pXQ5EuR#RB\hlan(taiGOJRnc_!F/X]i-U0"XfJ_\/kCT<;+j:?0?RePgd4dL")k2r/"]I*eNP@:GKrub#;Gr*uJhf):(+i]XB,pQ23__3#%]=3RC9%=2ZtRj=c;S?#SCs]0'7.6#aV(Ykr;#r`Ui5/)cThI-*I$:)O6IWep\k/"Jpeu2+mrbARUC?.%'ba3B'QZH51ItO;e0Da%I!NQg[4)sRl7+[D;2K6[Gnge^.T3PGOOrthQpij.UTW#=_V(a^8hu/3B??gkqOnIFJ@0_Q5`E,^2P4M?%3oCI+k"7T=CB2TW,*_)e/G,NFnbLg7#/j&&[h8YEnaU'f$0'-$/9VM#KP9q$Pijs9uMTO31f<6iE9>l$3!)A;t-C#bB@0E$,GFAq[%jUQVnY&]`_jlmQi_lp3HLK\%G>Tl^3,sPq[L0]s,9\5H\e`A.`-4'=:5=6EPp,R("I`_BRLF0H,Oc?9U$f`%+/GE#IpL3@m+=Vc/R,Y7B&0rQH:qQ2goaqpIf9,j?[@+E2:qd(o?UaM7!r&+6nRk+&4hAr:oe7ja6^fU%3kiK]6(j\8c$'RPk'CU2&5Y;l37YjMU0(h4Q/K];ksO3p\Z%$ule&cigu0A;GRLJX7KD(UNPRR54pH!cG^Eet"mHSiLkHrn_\=/[X)g2r7ZrlPbqYfoHOsUj:Gi([On\+mrbARUC?.$sfB&'e0H&7sodZqYH0^5Q">XY^X%O@_o_hRl>7\j_NGK.;_^[\siT=+@DSf%<0/O1`>9o7\C'2Vo]L"nrt;Bj62els+6G28BC-dq"8](kF$dSL-`%a]!r$,=IK-nEY.K]D4S-cQ0',knrA9e;V59Hc--4EXQ0(pG>d-:aL:E!NBS,&S1;oeIAOnoBo<\,e.:7MrQ+aiKhbR*6UI0N:ap/@o7-.3.q.+2DK)Ft?Bc].I"hW5oLjKti-J4k96i>&)L9r0h5@=?SpUf1gD0tEh)-,\qqqZ>Vc>D(0Oo;;=\)2Y(l3%:q^AI?1:KShd)^?c^PR3B=3G\#(i!)]P98R]7E!7n73'AQa.&9q"J(K*Mpq9(MTF;c6NCDH.cB[Nh"'i&l9np05&SQdPBemW!4Cq&FaNrR*IWhkNNuHr.h.\X_4cDW>lqW`fro>Lqg-L2=#4f*AV0UPj([On\+mrbARUC?.%.P]@):B#cZSmo;SL_s[#.S&bRLF0H,L?S*dq"8!H-24lOIrq3r9R[&*]:_:]@1;HHPh;\fUX?Vr5hll["J:X%HM0b9(St^0%c^A6eoQb1r8T:)<+G`18Gp(o(.?'$#aUm#5Qr_dQD8p$[/Gi&GIj[9s?]RLA6t1$u*b8r9Wn@+5e$:-?!\5#5Qr_dQD8p$[/Gi&GIj[9s?]RLA6t1$u*b8r&e]AUrQ(0Dem#jq:W=,4DKBSG,NFnpFlYCYWGR6plhTaBubo)lm!W;4'.k@%<0/O1`>9o7\C'2Vo]L"nrtd-:aL:E!NBS,&S1;oeIAOnmpk3'F)pWf6eDq(^__hJU>qKJlk]6.G3r9R[&*]:_:]@1;HHPh;\fUX?Vr5hllZt!KmSih:=:f*8PSf?5i3cP+Yd_^HDOd-:aL:E!NBS,&S1;oeIAOnn[jl^C/WcdUV8Ne+UF=?86r;:qXBjtO\p[6k*RT$4.?G-3Z_)W65'BemUiN'J'C:6Qk#j=*IM0eGWalIDq1SN?'+Vk8G'n*f/EF6>>lcHt$ObEgQ)[Vad)2UHf4T:ILWUB\59GFAs)+1U+]gbEW?rqgpFGq`JYP579NbrYParW/R&D`"s,gI8Ct"($$N5g&:a88+mkY_T6#'p^]4<1UIUBFV^G93Uk;mR>.&s7K@kY=1`>:KShd)^e+0hQOIr'oc(bKQ@!A%JBca[@N/YQf^lp-A=s_Xp9qt+iDr3bQb5M20MiE_0E8a-4IfAT\Vi0I'Z=V3m4"nAHE]LU2$LCNO+o^OO6eXhTect]OF/=03!#OusP9J2Gf!T;F-;Br]9@g:R:Ut]2b*DC[CY#T?ZY.V.bfgt_C/CIgR$bF*k8(I:W`clQj\r'PQ%,Pt_!X#si_Q.$U`Et:oB+;eT6fe%OTj)6HHP'\P6:^]h@!A4Z8&Eb/Of*/p+((KCl3:'D(+o^OO6eX7K5QC5j%nT>alJ$pi"fTI@pu@E"Ejs>@OIr'oc(bKQ@!A%JBca[l\@e>1H#9J+tcC?mj5Q15,%mEP)2_)K$P"V_TG8n3uq:W=,4DKBSG,NHDk#(aJoB.>gN_k"t8sR\o5Aq93SiiDJp[6l';Rq5Qp/+[aB@!0OTOnR^h.\X_T0-[U4/V-&Hg\G"Eq2R.4d;;"B.p08f]^_XC!hA'h8e'S14oGj>\P6:^]h@!A4Z@js,F!VV\XFTNAbY-:hBOe1D;-2UrpINp7&bLo]ai(n<6X3WOQOJJDFop`1K/'83<^1kE(degMXX*W26kW.d1\E3J.1q>\P6:^]h@!A4Z?Q!`1K/'83<^1kNM-nCTkF[W26kW.d1\E3J.1q>\P6:^]h@!A4Za9V50mi"U/IJA1UokW,::to_@I-5?<\'FQbu@frCI2SXl.8=K,2po^qcgSp@25X&ae&JSWioXCi*5^mmZ1liR5K&(,rUjqOSHqr#;CUS=K]EpM;Ym?JENS8"7Z4*Tt'\s$QHRLJ^6:DqT@C&*&Gk061X6'Wp")Dl-SRPelp/)\,8hRhg.4+`*;C!i4u>I`GO--4EXQ0(pG>d-:aL:E!NBS,&S1;oeIAOnn[j_*S<='c1@$aXaJCu#Ac$>C)rlb!Juft#NnC4H\8Vo]ME0EOtQ4&(J)PG\h'a2%UHm,,SXd75;GgpqLd!pIIr8WsM[1:;a"IWhkNNuHr.h.\X_4cDW>lqW`fro>Lqg+bBJMZik/\^ETTJ.$OuaUn2#!_om\9nrG,V[R8Eq,nZXcd%g<;$1(-4&(J)B2TU&*d4I'&AQ\)83<^1k9#3OnN['Lcd+iUCmAhiZDD^0f&>TH9q!nal`IW5gK$e*T:ILWUB\59GFAs1c_N=,4R>h,+b$?2OEO=@cY7*-JUrCLp[;0Z%j*u?[;&_7>seB,'GU3$QXBApp@[Vt%e1c4jsl-np3EcQ3<`Y&1k[6!UmC(cJ!`."^%.^`GV0UPj([On\+o[m/L5^oDBemWq1`=`%C&.S1b:[S[W0)D=C=Oe`J,dWS-X05jp[0%B*R3*@Z@`#@>\P6:^]h@!A;G^^Pp,0rGFAs14&(I:@p4>qqsM&u!WkiN)RXVIb/D4dHG!b.%VodrL(.@qCrt>BZ@Ml>>\P6:^]h@!A;G^^Pp,0rGFAs14&(I:@p4?<]6A0m<0['Fh>R6F[haDhmC-&8s8D[J2QnYS5ER6cR%31`>:sRLEoN_#,_ujCdXJo;D[BfUX?Vr%k;\)%X@.A;K,W18GrOB5JbU4'.k@%<0/O1`>;F8S,tffUX?Vr(`G!m3"W/"8UW\dQD8p$[/Gi&H>ER6cR%31`>:sRLEm8q,nZXcd%g<;$1(-4&(J)B2TU&*d4I'&AQ\)839"uT-Uqtj`CeQ)SFp[?\8>>.^aI!iRCbs6`$Xu)1Xi.Bd!1;lD@b)l.t4&(J)SL-_XnV-m'If+EtbfRuKVb`pc-*q4.U([>VK,;\uh7H$A6Rc`!p=X(ZiIqXU^A-[q0:IIils+6G28BC-dq"8a-C#b7@<\.KnN0I"Zm.b!kN1eo7Rg9ZhS+EM]tA(.VGt'BgU:SBmEq[6eQKS3Fh+j^q:W=,4DKBSG,NFns%Fn0`l%4$)<,k/$u&4ZIbqSS,@t9W.k[\mR6p#!-;>t)`I7XW"U"tH`Pn*D99>d:/'Xgn\6sNL%.VZ>11WN6:6QiMVob$D9ZYPD-VpTrHh?N!osf7FAuR\[R@-W,3@,ujV0pgneG;9<>[Q+d(+5\Q7ZD>_3T+/B`IIpL3@m+=Vc/R,Y7C;k2Q`_hH%n%N"SpWt*6.Ve"`NF(ruo!'+R:7XFW4YE=(D1)-Ji=pUYO!!gg^1Yb5.SiT+-u-`.Zo"co'GONK>.%F=IJ)6tA!HHf%2qWgOcbbPhYuq`2aThtOImOCc(bKQ@!A%Jn^"!dA3B3RP9GCQacL[>aNkTYfD/RO81[uRb[0/+<@]PHjH2riIpM,J8^]_9J.$OuaUnJG.RV4nmPGg@GFAqS7sodZqYCZ/@RNUPIX]#Er7P_TV=Jfsg6K)m\:2?+dQD8p$[/Gi&H>ER6cR%31`>:sRLEoNr;:s1gpmRr(>O9*^!ilTpYrf3?@RHDcC?mo_7ap@XBAL"#M2Cqr9R[&*]:_:]@1;HIjUF(j'd/#%.QDRL9tGoI\&ZIE^2n*`uff4SmJpGTj>9Rl5PHL2a0G)q!mC@g7['lYG4"ST.G(5?a=2KQ+(GSU/]CIM#?UMBc].I"hW5oLjpb:+ld!TRLJ^J9np#b>(43JRVV3=X(OS$[VQg-k@Vu-4nm`Q]mKLNa%nhf7&`(XrI2mj?[ZK=0Ced8cCI$uUIG]=`UCSAhHm@fM]Ocm=K.a/&c(,%dQD8p$[/Gi&H>ER6cR%31`>:sRLEoN[/>dNDVi$OBt('j^Un@;[V*mU;'kYFh`Z2Ogd[8AN>jh%^>dYA;lNre/mV5D4K1q:pu$csPq#Y0hR[iFBq'\Ols+6G2'Ot',.EIXVr6%:8a(mk0,i4p8jRNE$"@@P9Kpn#5%fkn=dH_sg]6:%A>.&,$(9rh0*?pKB,4R58JRrS>)0QY25Q_!X#sih&eRaEZ@.-:@]+P9K=\QCh6^?L@4M:Z8!:N>h):)gQ^SC=.kO-\?u'qtBF#gHr)0IWhkNNuFQX2JLUX?F#%YH4%>9=0?YKXR^F#6j3Gt%hBaAE8]]mLL'2lS*7qU,8@oMIf&N"R$^N"^%C*jEu!;UkJHXD)<.8[A]T,KSL-`%:6QjgR$OA$H1U1KX&gr*/F;)+YMHa1VcE`?1XAn)?EdfQ515sYe`$22]JM:Z'\c2)VBeQ6*pIp2q8lqW`frg?`?N/-5'1;rW<):FOrq7.oZZa3Gt3-"rqH1$E3$1bEDV0USMio5:Vk[?-db0$IBS!f[Iijoi"WTKC?5%uZ4I/*19++3Rt)fOM[pYEs5a]l2i.H_I>J_b#q`'9I.OR]P:9nrG6-:?KA/O0!th>\P7e;LSQ2:/">TQS)R$=upfke;/ndI"/@sfUX?Vr%k;\)%X@.A;K,W18Gr>noI>m8ABWP\6DfR+?qqhRRaJZf0?mrW`?*/INS0:++E]AMYe=Y:6Qk#R8ep"LYZZ"`:#N#dZ/&;\T-ZL2r/QhG:P-GjCdXJo;JL`Vn:`66iE6FU%dG`+[81U3]d,Kl`Mb<_N#WuBN%\ioi1ao<>OprP9Kpn.H@"Yn&XT!@WV\nufW_%NGJLJf4&(J)B2TU&*d4I'&AQ\)83<^1kHegIhJg@AQX+dfgMahYlrSq(T:ILWUIM&TU]^i)ARo=&>-t5FgU?bLj,ZE*M`PtD5QTN;=h/S7+[_".RPg"do7-iDr;HS`2fJ]YT7noKEf%5,?ddXVB#!s<%C@iP?:\@=Nd2L5]#ZZDsge1MO7k$WL]H;%"+84Z:P5H2S?VhH?=0EZ^-TjN(A]pCGB@"TBT8So(0G8lR46o(2P+?XKd1V9_@&b^In$c's?;JpR(QTtaUh!qN[=`IDE[+ld!TRLJ^J9nnU^h.\X_mkbp1NbS;L.OqH6f<.OoV+"?LB7%c5jCdY5s2Z(&sC^L5^oDBemWq1`8%iG,NFn^XH^a4/V-&o^m6TJ,e8A^]!rtj7`&--Vk3i1*dtb+:sRLEoN[/>=Dkg?oM36K?CX&_qh9c[.t^OH,*,9nX=a2c4B4*HRpNF%57ls0'&).^g5fUX?Vr(`G!j'd/#%.QDRL9tGoIO9O@mC/R&]#ih=.\oMgXn*UpBBP0Pa<3ji_sT?!icgh")%X@.A;K,W18Gomo<[H>T7:1[Gk(D-kQ*j.DGaP&IWhmhNsmdS4R>h,+b$?2OR]P:9nrG6-:?KA2F#@eq:W=<5;L:sRLEoNjSXE#nDWaRh.\X_mkbn;*d4I'&AQ\)837%E,/$E3iG-/IUrV,2fg9`:tBWAku[PEI4ls0'&).^g5fUX?Vr(`G!j'd/#%.QDRL9tGoIZB>EX'WL9s8MaWpI.T4*2,e1)DoguWcA.9ft$*,1<>RIYWGR6pmia!`l%4$)<,k/$u*bhr#?Ung:)"XU6bN;dt]F:Cem'Cr9R\Y*uSV1GhAQ66i9]C+ld!TRLJ^J9np#b>(2KmO71c.B2M<9;-[@rcM!JIaNr-Hs,fU%N/-5'1;rW<))<7VVo]Lbdpu!2VWHu2++5t.4T*fM"rT0;G,NFn^XH`7GhAQ66i9]C+mkY_T?j)lHh5K@f;i!A`>;lDF68E2U^-r!pV/Apo[9h=A3B3RP9GCQacQ%s4&(J)SL-_X6%7Aho!=HB=GY7YTXb.MKnLc5$AA6&(>Rh.\X_mkbn;*d4I'&AQ\)837%noIc0<7e9YMcr`2W.N=gPU"8qc5$AA6&(>Rh.\X_mkbn;*d4I'&AQ\)83<^1kKqT&!rX"ls=ZMZ:a?6cR%31`>:sRLC&E]@1;Hhe=jA*RjS#H@!0;^]3]1hgYLuEI7N'P:)+o)%mJlOHG[Ae[@5br9R\Y*uSV1GhAQ66i9]C+ld!TRLJ^J9np#b>(/Y]oOqK7*9H7]NOs>iKDb(@nK/WZaEZ@.-:@]+P9JspGFAs14&(I:@pjadr;?04M\e%bKhbD[-68RDu"9,-RYfdRl1t/.64<'VC!T8dGsHSkcCj:cSs:W@n2#uJ)k8"'`X:]L5^oDBemWq1`8%iG,NFn^XH^a4/V-&Yct?@mU,,tj2[4Ygmah(I/mW;^(Hh1bdnS)QXfaH5qr4&(J)SL-_D_sT?!icgh"BudUYgoOYbl`Rk&*&j7OQPUMW8\''Bp?hSEVG3OXiO3UX9&.;B_hY9oYMQBc[gt_$&Gb!<`IDE[+ld!TRLJ^J9nnU^h.\X_mkbp1NbS=bR:i)t#mo:uHZsaPE9"rt'RJg"j'Bg*9US6/P9s!RE=;aAoa;3:sRLEoN[/:n?JA8jK5S4,'#*s"V%mKb2KjOWA;SHY]%OuDMZ=PcVSiLlSdRu61e>SLen]9$?/,gcG$lKSfdq"9lBej3]lqW`fI](;LG"g**PZR1;7&`((I/%Xf^#R.oG:DFUB+L7Ds(gO'4R`@$U"HH++mRB`<#kG;h`IDE[+ld!TRLJ^J9nnU^h.\X_mkbp1NbS="h!mEiJ+:Jo!OR]P:9nrG6-:>ejmPGg@GFAqS7sodZmeVoakKYr'hE38;lAn1/YR5CKL[1c'gMb_J7W$WMcS0$1bED`IDE[+ld!TRLJ^J9nnU^h.\X_mkbp1Ng]]g`JPDd\oeAk%p.X+U^-O6q=T!ZBoq;q^E;jI`#g;Iq4Waj'd/#%.QDRL5^oDBemWq1`=`%C&'bF1R"PRmFnra/mNYlj@N?rlI;e%M\]/57;/\tg23kImr$mgm?obCh,+b$?2OEO=@cV9ib#nIRHq<+C+(Ju>-U'daQAkl)rldi0eqSpOpVP^5ja3i;^=]nm.SOo"l;;pHLK8\Cmo!?Z"s2Z_`4c2#lMT/q,[k\O$TK)Ft?nK/WZaEZ@.-:@]+P9JspGFAs14&(I:@p4=&3HAY0<7J0_a4qIO4aOJ]p$2;-GG"k8Pmb[Zc5$AA6&(>Rh.\X_mkbn;*d4I'&AQ\)83<^1k>S9R?%)Crc'pZLY[N0tI,i5+/R,ZZ79"i=D.NkGft$*,1<>RIYWGR6pmia!`l%4$)<,k/$u*bhr7n8MVm^HsWk6g3XBG.p!huHbeW$59;(!Rh.\X_mkbn;*d4I'&AQ\)83<^1k?gjgGC)s`o!h,+b$?2OR]P:9nrG6-:?KQIb"_oZZF*8A<7tp@<\.KnN0I"N/-5'1;rW<):B#cZSmo;SLa[aK+&V.]@1;Hhe=iV4R>h,+b$?2OEQ_X[=S8B>k&mRAB9#JSL-`%:6Qj]@<\.KnN0I"["J:X%HM0bMZ:a?6cR%31`>:sRLC&E]@1;Hhe=jA*TUjM+?qqhr'pr/1*1V:aUl59AB9#JSL-`%:6Qjg+?sWDq:W=<5;L:sRLEm8q,nZXcd!:*O[4_\LYZZ"`:#N#1*1V:aUl59A4Sf'ce:X5G-:V$$o2?UlqW`fI](;LnZY)LLA7;d6eXhTect]OF2`W>OnK/WZaEZ@.-:@]+P9JspGFAs14&(I:KD_e[jCdY5s2ZRIYWGR6pmia!`l%4$)<,k/$u#tB=W>H.c5$AA6&(>Rh.\X_mkbn;*d4I'&AQ\)83=o=g-C+1Y5"%d11WN6:6QiMVob%jYWGR6pmia!g-L2=#4f*A`IDE[+ld!TRLJ^J9nnU^h.\X_mkbp1%e?qaOIr'orZd%()%X@.A;K,W11WN6:6QiMVob$DOIrq3r9R\Y*uSV1GhAQ66i9]C+ld!TRLJ^J9np$-r2^@gBBP0Pa<3ji_sT?!icgh")%X@.A;K,W18GrOB5JbU4'2>M"rT0;G,NFn^XH`7GhAQ66i9]C+mgC:CBOCc\`,h/aH5qr4&(J)SL-_D_sT?!icgh"Ba=H:)p$@N(&sC^L5^oDBemWq1`8%iG,NFn^XH^a435b%5^mmZpl>h=A3B3RP9GCQacQ%s4&(J)SL-_X6%7Aho!OR]P:9nrG6-:>ejmPGg@GFAqS#PhLAaNr-Hs,fU%N/-5'1;rW<))<7VVo]Lbdpu!2aNrR*IWhmhNsmdS4R>h,+b$?2OR]P:9nrG6-:?KQIb"_oZZF*8A<7tp@<\.KnN0I"N/-5'1;rW<):B#cZSmo;SLa[aK+&V.]@1;Hhe=iV4R>h,+b$?2OEQ_X[=S8B>k&mRAB9#JSL-`%:6Qj]@<\.KnN0I"["J:X%HM0bMZ:a?6cR%31`>:sRLC&E]@1;Hhe=jA*TUjM+?qqhr'pr/1*1V:aUl59AB9#JSL-`%:6Qjg+?sWDq:W=<5;L:sRLEm8q,nZXcd!:*O[4_\LYZZ"`:#N#1*1V:aUl59A4Sf'ce:X5G-:V$$o2?UlqW`fI](;LnZY)LLA7;d6eXhTect]OF2`W>OnK/WZaEZ@.-:@]+P9JspGFAs14&(I:j!4@[4$.fK`/+d,#pCH8Z*CQ$LCQIdi'?h5*'\n"l-cF,qtI:$^OE"OPp.CrP*2!jbaEPGlrif2JGeb=nK/WZaEZ@.-:@]+P9JspGFAs14&(I:isYZC-RYfdRl5_EI[$@$;c>+Le)TZUkcCke@b)G^IQUX%p\/URU.)hGrAo/j9\Gn-Y.<\`5QCZ1Me4(r4'2>M"rT0;G,NFn^XH`7GhAQ66i9]C+mo%kITB$"3B?p-l-lYCeuW"Rd\0$`@b-u+D;(@3A+o?HCR+hmj,`lueY)RXtD'>k&mRAB9#JSL-`%:6Qj]@<\.KnN0I"Zm.b!kN1eo7Rg;>h7e9FV7#U?YO=nQOIr'orZd%()%X@.A;K,W11WN6:6QiMVob$D`96(&prW6cR%31`>:sRLC&E]@4:>k4/2;IV7-XpG]k$DG/[Uh>3sE3N0UD]mFs(<`Vsj:/V!\IeI_BT7$3$E,`%r^]3&,^[4U@jC_'DT1NV8GhAQ66i9]C+ld!T)N-"+^U3.0NE`jkhcDnSh!n+lp"e6STQ3lJnA>c$'G[=\kN?lrIcHo9^8YGP3n8`BR:j0M$*N0)Y4uX-))<7VVo]Lbdq$OEfU^$VVr-/qiVCZ8^YeSIOWF=ZQT!ZBoq/q^KRG*P:mb/#h7LTgMKN->&)W5n^"!dA3B3RP9GCQacQ%s4&*JOT?U@>JGbq$PLI*cCJ)IKZ*>!te`5lWB_s[GP9s"u_SLj0>9seBn,S^V"pWq-gMMT!n=gfAcd!:*9I`EL_sT?!icgh")%X@.oF(KJ>ZCdFcU;r"p;De$j5]0PK7dZC@YP:/Z@Dn'HNj0A9TT.0`eu_t5r2`1+^@@`jLR).F^21"Eg%(K`[;'#.1pg;*NVeM(5Q0W?G%]t"k)L<8-8mb?1c.$<.;@VLFl#+uq:Q=@T:IM3R8ep"LYZZ"`:#N#1*1V:kuTV8=iWVIQh'ah3sWFhbi>"LI'^YhnC@E>Knb>h\>&MF-Qa3jo$3>Yi9NJ4[6(^Es8G;M60[XuM\[m::/7\,Rl5-S_VrS^L4K3g>k-.911WN6:6QiMVob%jYWGRoOIogCPI9MhrbWC4TANcCYG*N=khIf!)qk2bUAa2_,9p;5e0c\?uJls0),UbZIClqW`fI](;LnZY)L^RUIZ#H-@)Bq8@QaeX^[qZ":@$0n5U_[#GT:[PFX*^L^9YQt(D_:p0q7foJ\$'gH;Y-2+>:Nj#mFns>P9tIJY$\r8<`utRASE0Fr+lY[cd!:*9I`EL_sT?!icgh")%X@.oLiM>*h@J$5X<-.R?OaAT&f(E9C$-g[+VI@qt'"EX#PS(HrW^.0El1f.SUNojScAaPrq2UK1`l2nD?POs4Qt0qV9HZ`EA8)GU\jIH&_+>6:4,K^]1<;qSo7ZdCPs_rITH_Paf8'`5F'.-71'_mbHK5e6T\0d4,M?/hF-BOe3'`q:W=c5#3gK/\!fdH//:fE5L6gs$b^K:0fi(=^/nbKM0K)Ft?n^"!dA3B3RP9GCQacQ%s4&*J[P+RN*]&r/^U]0M@T=];@Xqb4eYu1GHDa1V\XC(]7Qi)5*;KJ3&luI0+a#!.W_ID`AZrBBP/%-C#b7@<\.KnN0I"N/-5'qW3t>4E'Le8rOIFe^K0*hcElp\E%:KY[uq>["u#jomOWi2g2;c(4=:qD#R[TQq>%"D:;+BD^9ejlA9hVfJ=1#WIDjlMd]Cr\&R7V/X](%*SVHpj-.D/4qBqg36o`"MGHeu*HJ-3]Zhs^LAI\-#W1NV[u391"`3T#O!-@a'J%hJC>#52)agt+J.37)%"r-s!7Y4u`RJ,HQ,Q8prcg@p*"W2PN.Lkq+QYK)rU9bYkgi0ZkC=>m`"T]OZY5?ho(!YSAcr8@REam(\@Cq\\(>Q8d@ZglIl;3.YG?2l4n;1.,P70H8(]&Y2#U?GJ$+"\e;BA,irnSl9V=Th2tU0L3Plj5Ura5F8WtCcO\_GF6%A#9-Uq^EW>o?-I+%']rM7OIp;eUUs.DUJN>%sL1P,OAgsBD"jTp4oP9rf`-V]W*7m:Y`#Q:'/S,iMU$1qljLAjdp8(]&Y1c[leBl\kink%:pkg+Y:"R+0*TKaASoN+pN_B/NKaV"A@P9]FV:R_8KJ*%[t5_!AIrRn]S^QQ_Op;eUUNmLRj*+=nUde"(H1Z(.mqD/fKcc-FmPuNdJ7m:X-KRVA1#^bWrVLQsbq8N`fT:%ro2K%`^UiM,Onk##ioTLUlfH["Fr?G$dG&_MiP`eFAHI8A$%d;6Y%K2PkNj)#;Bl\lUdc:[\jHHHjd%>GOfs-%PSX)=8:XQ>/EXnbtiiZR7X,>GI\s`lIDs#A7f@_L^d9];qJ*R1N_hWEI603:$SL-Kn]O*rYCE'fs50B^A+G$cs=5)d;H*RIqAc\fsm`jP0+C1a;F3e#,tlGI+W^[@:s*5;RliCu!BE8`^5)jHCo\kU0)bYX^lkqSt#_q6@m8_a9!`9BJD9P\>n2p#cMC',rfDPdt2!\1KTQRqoM#h=Gh7b3e#7?$#&H\Sj$fSMmoV:k73`r&:77*n`])>]OqA#Tmug`kFY2ohENbZ!#mfg#UtS0>0&\@Rs;Ejm0+b0"1WQl`\i)h7.I"=L*/>?KH(JQ7Wa`'=F#D'c!Q_Y(cl!"T#HE6[pDI,OCOgRN/#n1c`Doq5!6s.JpGb_P.7X\T.%::nBd-9O0;kPHiAs1U*M\foDRPKT4g0?M=0lF4$,(ne+>k!+6W%Qff^[nIf6f*GIpteG]oO!iKt3ERQ#/fN9-7!53_+f;cQho%dJla-c@@"R@1hGr9.k4n;1n5;MopM2rs?$LR9L^@ClMg,89^cd0oSDtEj,T%SV]n?.ql47DMQq9XP<[@=i,gf/F(K:gqD6,ha50!.WnhXg_RPZNKN(XDhdW`XNFr-:#_rVH3QfWh2p:dt6rO%u6,!rRn]S^QQ_Op;eUUNmLRj*+=nUde&SorRofC>Pr^,U1^U:[AQ5nrV6,5@I@q&SrO(pmH3Qnno&pi\nO+Vr5KrJ&#dG[m16o#o4P!*qQk0/IjL@)m#b)4*2/u]3Plj5V!/tro]MGali-h;e0hBpo:S91!s;_KC2YOaZmL?*3tp?WY"D?"$%q7'Z6<7j$OY`hH6e^7N#PV>.@(CngQ7Rr@Y@bPl>(l^tl(^%(r3R@lb`2tU0L3Plj5Ura5F8WtCcO\_GF0hQqeQ9)U6T#qG9k-LBe(Wd;I^McFMAMlsND\28jmEWa5>bah@F_!hNA(:9:-9f5Y57mCNsr]\0VF-r[sfF%qm0D8pAQ&d\O3!\s50I+>ID!79cWNGj-(STo(5'9jYl5gVjhV;s7=Bu/![@j/1dn%rm)`2+mSqhNupUCbKK4qR5<"A:I"eW]=A^R1DAuu`XVm3<0"1Q5&#%jIa[9_HfUBfIuMgJcQ1m(j6bAL/G.97cWHPh\TOqq;/pAts14ciXtlJ@6i,VemJ@inH$e*LjjhO)(HjiiHu`%VInP$"mJV=uZl=M/Q]cIjR[9Y9o#.H6^!gKZW<&h@dP2q$XT[I`gR"/p2A^+8N];j_a4Ib^E[jTTd"I]&nISU&*XW>4q'9P<%+4,mO\OH[0pp9tpDC]%T*RAUb0t%XX:RW8sT/8RF*r2Vr+7s3[E<>cF-IABE)u;(a*+=nUdc:]4Ura5BaWa7IQL>bhD[*(Q&2XfSV23WHQ[J%fsbb+(J5+sS>WAohp1nDfQo?;sm7c\=[ar,Z%F>+7Ee9I>tun'n=8c_!F/^O8@s2K%`^UiM,Onk##ioTLUlfH["FWq9K)IDP'l2t-O961W9u=\&Y5#u7*VIJNHqRcaWnkg/APjZRq^E,fk0brI4%WI+C-ic[RP5X@\%m2M@UPXIo-Lm?`&CF;%,e>\YA*>K;h>$>*jh*?HJDWn:"EeHUH8WtCkP9rfP,G-gH[(Z9Y*004YoDV8_UnQK>RmF12Tg-kp4^7R8SiqFdQ'EdkQ7Q/_QLsV$]Cl\(NuflR)_kg?YJ:(:/=A8)MHKH%@uo/M2pe1V)u;(a*+=nUdc:]4Ura5Ba&oas7l3047Bg\/BlA`X_GZpIe^b0e^\1c'c.[e$S*\V!WiGYgt[AVn]/6/$2UuJ6[r^0,OCOgRN/#n1c`Doq4u+EqFQkq\s'imn(P0BoONm!@^UU_r:sgt]Qs*`g@25Rh@_@2n)*#;q%HOd+dT<;]=+khK)TTAd%;3:#^bWr-:d8I9ocGJ5&#%jIa[;5m\K'hqH#.;59cJt)/QPu^CmiiE%mKbRGu8ZhpB:HJ\=l,Ca:\-e-V]WJ:RW83O*oC:#lUR@&`$%9T2SZe7GXLtHa_Jqj2[4=jcP[f2/P<\^]:XVRr?#T[6-N4>:^SOf)C*dW5dB-kDfODU]J=Rq4u+EqFQkqm#b)4*2/u]3MJU_k^7f,lW6diJPUc=F)r#peGB2@$k>&M7(jB:`dm(Q^j\7LN(Z"=^qdb^l(8&>`"G=Se%D[EP?3'>Iis")poDWl?:cQ2jfFQ"1JGjH"!*eaOVrZt$Bp[TSq'k$Y8o`q`;o#&FIKQerNY_]miHPCKPgAen84^74l&r?JqWE&U?bX1$qt:mF);5ObcgQ>XiJ5t0mnQMKX7te$K0eJo#%0Y80*(^`nH,5GQ^>b5a,Adn*#tK5Pbd(E#RDh,-rAN`2fE$q@U)f/@^0%"Q[ar63ANWV>'\;OdaD%,T**HVq$k,g3*lUOLZ8Q*]5m#US2kXY%5sVJ5s[dc.4Kt)L"[8Xp1HZjjXF-*Zu4]'Caf:PQBl^nr-A87)ZTj+q>f0Iqo%GK7bO1nYfP6c:,-jQ`n.".O-/_2E'.Dhquo3ZYeI*K*Mp9qsClC:PZEBQ^;?->!mcD%X9$JbEjju?T'GdXFL9LO$A7g9W)9<.h:/,cLZ-.+MsG_n?G6:7r5==5+X,UKD6(D$M%_8VNZG`HeZ&]V%Ytc:qD0hAo6;^o8\:e.\2ZN1>&5C_FWI(u5XXOVa=."tqPP\C!8+8G-b&AU5Ihe!IQSeu_VO$rb*4>&:S-'"<*in&Q'Kn2FmE7i&tXjeqD/+2aH9i4fmNbNWDf^Z7k\,W&/cA=]Qs+p55VFYmsafd`;p&F\@T7hfs7HOFjQb3&,sV-C@gT4ip2XF3RZdI#2fVH%iP"P!-"#E-TCRW`F9EP"q;KH^4&cSeQYX?o#i[E=$V6>5563QMP#Ct3A)pZI'<5/fA$8b!#cp)6Up=d#mgnU)&]EQWO$3]qWO]8Y$\s3^_6m%gP[:(\)1s"jk?tLa5#J*??tWIFifXa41]S#-;Jb.+X,j0Fm@I*Z(^rEih?>JpP[cVQHaS3`QBkSKc_pkd_"3XJGjo*eH?r=]:?bJ^o,^&@M"S['__59)i/E-j!0E.c#-70p]C)]na\A:`7ZSUmhX/afMqMqGo#i\O]AJ&2?&KIMZmW>e&.3V[EL6$g$G]o-$VQ\J?#!W4nC+@:>j3-T*b]]7TUVFR$tbeuW$Bmd;uW"8s,4i.&D<[VXV@2AnDhfWCb\JC>A!OP.3fX38b39u#eR!W[2faj%`@A+f-;b3aWSp:4.L\`SYhI],E?V50pFkKgpcs5QOJ\HN*=/7,tk\ZPes`_.tuUg7EXVG6?t9jHmDG3h1r^]9k9Jc6(*n3:6dg9bQ=[ONm^^@`-AE"2sj1-%?T@[!1H(qZ@V!8QEN4Lq;cVMZ\Qg"BE\G3d^23B:6Q>uk"gmdAr0:ESs2.4H_2amHe9hK,[lNOI3+JIhb#MlNGCTM_IRIXZa2Q'M&+3IlisTL1%h4^G-IG3i?.Sf%O`ef6f_M;-R1E@/o"3AVd#5lJ[lW)9>.C=B(V0.JG$.4KQ8eQ:S^gr,B-?@-Pbo&XJi\SpB>2-o=kT7INEa%L#Vk1R(R[9rF8n%O^@Nu+9ZSik]"-OeoMSqkPHhLdH?\GkOV]ZW[/02$4nMSK:!*^FL4k4.GK'+Wr$".mP+=BLrkX(tC&9O_Jj,EFr"(DeIeMD]bRl;^kcf$OF$!-Q*NO:gf7,:+cfl%''\B\Ttt=A9bmeN`:;!5Kod:MrL"<`X$QXI#9?ntjk1b8N*E7,u:H^]+(FjmJs*Mi0pt_pZ8-%9)"m:b!!!9>(Dhj[KS5)7MGmYPl\Om([;4Cdga`ArE4c2##n@gQOB$aYI]HMO]Y(m41,>rf"Q7m=J).DA92&$nH)N73+N!hzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz!6G*\(n7L&~>endstream +endobj +6 0 obj +<< +/BitsPerComponent 8 /ColorSpace /DeviceGray /Decode [ 0 1 ] /Filter [ /ASCII85Decode /FlateDecode ] /Height 480 /Length 149 + /Subtype /Image /Type /XObject /Width 960 +>> +stream +Gb"0;0`_7S!5bE.WTRt%TE"rlzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz!!!#W#'=Zi&-~>endstream +endobj +7 0 obj +<< +/Contents 18 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 16 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] /XObject << +/FormXob.cc9e5c02168e1937e69f6918f0ce4d2b 5 0 R +>> +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +8 0 obj +<< +/Contents 19 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 16 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +9 0 obj +<< +/BaseFont /Courier /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font +>> +endobj +10 0 obj +<< +/Contents 20 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 16 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +11 0 obj +<< +/Contents 21 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 16 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +12 0 obj +<< +/Contents 22 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 16 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +13 0 obj +<< +/Contents 23 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 16 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +14 0 obj +<< +/PageMode /UseNone /Pages 16 0 R /Type /Catalog +>> +endobj +15 0 obj +<< +/Author (\(anonymous\)) /CreationDate (D:20261102110518+07'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20261102110518+07'00') /Producer (ReportLab PDF Library - \(opensource\)) + /Subject (\(unspecified\)) /Title (Lab 3 - Ukur Hit@k) /Trapped /False +>> +endobj +16 0 obj +<< +/Count 7 /Kids [ 4 0 R 7 0 R 8 0 R 10 0 R 11 0 R 12 0 R 13 0 R ] /Type /Pages +>> +endobj +17 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2637 +>> +stream +Gau0F95iTF'#+6En?RRW!%T8dT$+4!9ZBXN7^D9hjhbo?]4jE0Nu/)`a)@)i"$30_.!A]*`PeM]N@?0CJm@4'S/8g`oG=fY+Ic^Qg_We/qGG>(0OY86;%P_fRXfr3G.%)Xh^+kGI.`L3ROA7U;teVSKc^L_a>YQYrek^R]c6Ndei2YbG5oi_RVsh9e:tVPMO."1=k@qcYe`;;Mr3I3VeG0haNb#)LCp,BOt0rZU77;C4l]R8^H8,j\b_YBk^0F7#rI-rQ1_!A0=p`u-ZSp/QM7RA6H.dII>_GdbDnl.HD-a1V#l[ZA-(\RUg[pL-G<<0gsm#HL^_=+$Q#B905Pe8/DRIa>nXp\)T9s)!gN-Fch06`RAn414SV++?GcU]l@g5;cg.47,`[XEGJ_2/D".Vmo1ID]8t'R[MnW&NuP^jr0M^`U(0k;["_uQqo>]k`KhH.%SnU/@bd(g_k.GJ"lKK:_,qm0`,K(5PPcjDrTIa'A3rP7q@^(9[C0'7E^p+&njJa!]\e.tk;nnBB&U?X>-'?V$Eb8S)e??>Z?H3fIR8/75:H(MjfQ#-cZi(,W.'2?VRGbd)*>\Y,:Ae9Hnb.VIV$#02eDn;\.]Ar?N4?JHg&-Zjg#A"0rF$J4#rbM/AT'+GKhnG.B!f=&rQ,2W0@N*`_>hS\Yb_,u$BH+h;3DsgqSm%L>m_:9JB5kCUaP"+;3TUW5OSor%&AV(?Ee)tjj%?3(1(Bg=7[Vpn\!3`#.].HnDU=H[Xo<'Y\LYfM`QTeHQf09E[oB*U!c/^+V9_L8UW5EttYD:J00+J5-<-e`a_m(e"+B4NTO0hlN\&SdR%ie<_I/%M2QaGqooJDoXad)H)3mTL)CiD1FiC\>C-\hu34W]K^a>"bm'6I%Z<["fHsBYI`(n@Fo"3f=p0!fTTTS,R+7@u&cTI]+1<'e8=3@m-bkobj*l0=sDH$]$B!a<hGk4MrEdfTVfR_VX`"*bj'&"mOCuGU?H"@>U&Ok0DBk8YIQj/@L/mQi"L)Qb;'dY-k!sb\[C4F=Oj1@uRAYTCb!H7DpX`V@R0@D$5Of4+r%VXqRl,*2BI&PSU*n5LN@rt6P<@[Qj(nKC2c$O[Y(!TUPP?&["g5.Y63:I$GHDi@eDJMs]TT59YBSZLkVIoD)o)u1-OXD]sY$YHR;:*[*o*/C795+K[rkMGiO0juo#20LI*SCdEA>K=\RS3Mf5RV%cf^_`ADJ0dH-CZ(>`1nr6*T!+P4O;aG%*hqg(gSQ57H#8]M,%QGnaOb0d;>4ARC(cbGl6`&qGt,5B/rhDa!"k6;91lu-rNU`*onBGt!+XYhN\(KGaEMXPRuhp4cm=CMO.YjAT2?)!H_ZNEj\pME\o#M$bG*.>B`oAT%%/IJn5"e&u7H/bVtbQ+rio;WO+33Z/?\icNY7@In'"L(S[h6i[Z@TU/^,.3)"5<&c^o0FTRe\nQh(Hm.!6,@kU7K#UAIPK@`B_[+,(,(PC[piI^1L(Q+hC;A1Y$'T$Pe#ef^T&@S#\A1f(/fqe'_]E!jtXnfB^cO\Oe5D-/^;Gj;_7)VP*W&@27QDo"?siuBAg]'mj2ISdHE:,(5tJs((K`YJ'&.cb8"5Hl&sl_3(<[*nE*6()5]skclPh2oF_PV+N<`s]eoT;(IA%&D2]q"s.KW8"j`+"ac#=`AoKkN,4W<;&TOLK2[:4SP0hg2_qbHU`kDqg(68,&0iKHda2re?SHq@oC/=.EID#endstream +endobj +18 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2022 +>> +stream +Gau0Fhf%7-&:Vr4EGouX<$<]I+ucT-LT]s#@;%S1fL'!/=E,)MPN.,MaK,(P#0`)6klkm3V+o,hJ\>=TC!i4\WLTR6Q"o/V(t_B/oS:rig/Aqd?6*>h,`k,CZ?u(P"?!8:O:`N'd'T5!"WPFKWFi@>A;f[.q'9_I9;h#;-<*pR8s`!RTDpX_L7lVpTWPTLP++u\%qLi=qF6Fm%[p);m,:P;X9B1)+6$1f@3o'Ui?4r^iJa=@a/Gc6X.58o!-0>AuWYLPaGgkerTef;%a+-)hum>AIn'D(nK,@imFf$^Tr:NB(VD$d)QaJoJm68,jY9b>f->4nK3%TOekNGl=A-[8JOJ!'@Sfoc>+J9r=(Jcd%J>&.o\r#rX`KQqZ5cSu.r@[Y'Kp83kf6co1J+D`oW]89+cZ(Mq^:,X%;4)H&d!p4H9eoG)Bq>'57O(\U)QghO2&\Ls,F_LDB'?!.M*'\gjHrCdnFM$N?uDT>EP@>n4QDPO1Q>JpjVeX]a4TP6bkHtS)MpOuo>'>ra%/QR&pSXceKi0LkrS7-)3$bHBX@tn6pCd\-9F?aF1S+bM*$.S5Uu9pI!/oB1)3@;%6p%U+6da#$\F5Gla:bX'0Lh[R=(Wd.&Y:CV$Nkrtj3aMY!C"!;s;15tIE3(2b$Nb>HL5*h>@_bV$f@YT#qn'M]+4>iStVYbUe#3:X6Td,Z5k<^H^jC$!]m3DGn\0odM7WorA!jThqF!+N$n;3f0Jlq*=XVk3D(cf=?@".6?I\oq*)sm3[NHltE26XtnkFc-[?[c7_l%ZSJN^Btk]GTs&[bD-Vg(W^G/"k;+/DG$B4Ap8FdqJu;p1Mq3Xu=cGnX^j9#IA6U'o&e;d[aE(j+CLCgBaYB,eDf:(9Ba>p)4P+SNsZRb=s^n(*'<)eUf"lY\'HnN%d"GL%/'slC:98>to&=\n3="S=$7^V6@J`a9E#Z<:KFp(QIM_Ks,]9[E>t*pRsr[n#EEXf<`^4UIG("!$7R>8q`R20p5#>WRXT4k8_U.(HbK/+Fi.Wa7(^Za0QTj5#R>3oL>(I[ojKjlM@_8;1g=mQ>*=ACMej+=1daie9A;X@eL#u^&<@bk<90Tfci!`C:/d%oF,;'adLlD$C6"S)Yu_HGP-_uQQ7T2UJ"8$A^/:u4U,%bRh/Lhki$_i/u!#=*`8.Z47,u9\&Ef%VOOk@5R0Xs=j-J58'i0S]W="CM`XZ+p-IrIdsH)C:kel-m_AEMh>1V0I*M_dn_#-X[Bt$a<3P#'C!dK3=YKfNK:-iER6(5drc+f!L%R(/6"FMR4/BESo[&fYd3@hU%D*9X`,)MYXLd*6OUrIN7d-:(+k%BaCqcT_m8dI6-/dd4jLIKY~>endstream +endobj +19 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1225 +>> +stream +GatU1gN)%,&:N/3lq:sON!oa";kEWMVO9?k8Qtf301utP+Pp((ipkoM!FA1AZE5D4Ypa(4F3^q3%g6kJ'B\m=#P_j+9ZM%=MDfaF"G,@K'aVfY;P)_+rUr:(@sjC']<1J,LDMT;OE/$e*KYb"eB]TE!!jB(TrJ4>c8oqI_FYDZP-p@j!I!+b\e[0LXR]i1d*,(3a#YaqOIcjmF*2(5J\oN:"p#5P@UQT34.R`^E*:Mc/@.XZ1;Y'666n#Pj,6-eh8q]PeCIe-!>A1[GZ`hig*256hIAskM(q=A)a'3+"UA20,"]$_COk09Og+`agtSkK*Leq616PXjM#mqGLt5knQkft4//#f`@G1^AeQC'O??I^#\tY]dr"&Y]5NtUds1TTt]-$A_*t3b8BCLsb[XBVmhSk7-DAGpA>O%:BHflOM4$SHH8,77tcY4KiG:_4N6bIabWI/SeYE/BqA(74j%?KK,odI17j%E=^'M\E?fIV?'#4DZ9bm;PC:3j(A"'B0GldG5MWn`X4!>gB=J.ngmb5pdhaK*YJgJbQ2?8Z_&U)D3h-E985Ui\Aiao8gR9<5!l'W=;m)@mcjt,urjHAWC$3`H$\0[,5/bF6#IHGP#\5OZ#2!H;\?cHGp6*W*#@H[-NHo&7cKFk]`H1>89JXP<]>IW,MD9@n&C*:@k;IK;q96s.E&9N\nuskmR7s0Na)G3m1jc*gel0+1p$n'M&C`rj2a]QP=3tYs"u)ZT(\"&Ba[T@\kf^-#@/5$(6O2Rht&[*.Hq[s$doe02KLNRr!tKM"uu~>endstream +endobj +20 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2232 +>> +stream +GatmI#o4CMVh;GGB3)D3PRuFaSf!O`(4-1/&#V^)kV*5J+#1h,`?^(3b`0X,)/08cd'fu4(Fnoq!kE"e!0'D6uUrZjS*=E,QFn?Q:BJJ3I:Aoe`tDY]K#MC=*!c.l^o3p[/4\a;=IZ*V[5,Zeh*G-V#O*N1L%m??`I%:&A4IPlb;'Qj$m$-huEIS/0gtp5\,p<0ZmJ+3\jFE#HT#Z"uE!WpA]ZGWn8'fDc[+29S_:AZ1+NVHB*E@N&RcLZPTO6a<(0'=*=WM*isP6o*/20'Qj7IPePBY]q[m')g'2OQWL:h!Rdng6L=$.s:DN]!Mpb.kr5E,^GgAa[Y5dj>j9\mFED;>2t6@K3QNVV*#>o.[%*r"^\lobION,8V1rogVFqG;5d4/.3,Dm4L+H?D?n!O-RoDA#P,3@4>V8?U4@I5!nj?F'pe/hfN`,MC9Dm_nbV890"C\$FanIXgS"pL3@Mb44CsYu!hG%dW"+6!at+M/3$3OZ6k4YboF7=O^KfW$%u)dbp&(SEq#9RXDK$!J\:)jq@/OoO4$K=^kB/#oX'?&jTS>LciiV$CIB%+b$KTTQolB9VA]kU=W"PAH_m838PD?u"Q%pE4ntVLiU&-A0JaKYiF@`C@/.f,),LE*;InK0*pmS6%a1E!=2^O+Rs;S]A[(m]Suo@G&J9s0ouh?INQ"I]U^&`=EMr&P0"Q%Q;>ob3B`IUtY#62&oiQH3=!u4>Ug(HDqYU=n%l#`Wt8l,oL+)Aq:XFZCsH5#>u(cAog_ciDUruoPnh%ES1UC/,nH&gj2Jm:RVZopC58rH7YtPZlj4JoK<-\h,MmLQ"MmarU&TK&:LU!=XK+%8PbjKuaJ$;M#=?r5Rd]s!"3TNfrknQV#)LGh(CQ=TB1q\VuZ%p!:Oo5YOg]@%3>L#30Y)a#ZV=^Q,Dftg$FDL65O+-lW3.$`GWrZFmO3N2=aeZb![2X5%+hr5g(XDe2G6F6_"J;VeX>YcELn6AdgSrapdE>&B+QsbUZM'J#s+1+:;+KT;4bNpV8b:)0:sR&/f%hSKojtr]PdL`-ifj=Lcf4\oF')Ti-Z)!V(Aif"NGV,8Fj:P(Q)i)2S5T*q#moOdc]VV*NC]lU9@dN2Jr1lis#am][BF5k18_$'b&<8TUNKhL@>B?iLLd4-,r_a$:sB7p:uJj8MPSfPrdDendstream +endobj +21 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2222 +>> +stream +Gatm<>BALf'Roe[32%#$QV7je\aNi95:_'GlP@]@3O=6SrcJk8V[dM4Ut'j3\=bChq?;?e)Uja*UXgb=]D'O*eI5'VT2R1J>F9hYquIC[,ZI_P`-eQIfak*abWc3Fl:+GU#^`ZcYr_jqoF*kA.j/IJ7`PfSE'`*6Ib+)nWE7TWe(6P2,al[66]K1,/o=u?r.,"<0=bCJ@e1;^Bu@E8o,]+,1(E&Zl7AD/kq'eQJ?B,MGK=RRYrj00]!r;r\^.cqF9>*9+0Y24<)DuRJb4\#s&mg3Js!*b^k8W/D*#ub_1Z(OOCNo_3`coZPio?Sl/g]edi\lFVeT[bN.\F'+"$/c][*eK/UGOImW@A)e4]A2?@RXb3))u_@p4]43@C'4Q0A-+WmXWGdlb*Vb1)VZ`-`u1hP-<77$%2O\ffu@3EAAD)"Qdtej7Rr+,2E$*O@MC(1Rk-5!X'\d6PoGM$26NV/qK%FEW:("\/tkqI@g0Ko-jW[+Af+s6\,Cr.X=;j?EOZ>::@elVYg0Akc*1fFZGS+&%Z42rtno9s'S#-c;^g_Fm_;WpUBmhOLe;\6s#3pZ7R_`(u:Wk+hh_6(f?kT46'G+GhDe+\UH$1m!2sO^(2r"DC9CX)04Abk.1rm,H:ouofPi5P(8_VUXu]];?:(T7=r1O`=ufC@+deSCm^B<=;WT4Z4:!-Ukpu29Z#d/c5^9;A,_H:A0fA19cFb9&o/(ZBCd<)ljQkq(2T7Hc9,Ja!Y)oQn?R\30O5TNm+BQ+XDHF5'F?ZpM8@nHi9sTtAF$Ic/a*T7afqdSV@YMbEiOZd,ppddaCN6430&'-P8@3)jAMT,)ub*Ct0@X-o$8>'o9n$5g&\)l1k@CnrnoN0b02TgSX!_3\0#B[ECT2pPSof%s]A0?]kk*Tcj)&Y7)9[\Ijro^WcA&mJ\;\N\`mtSa6ilc\S&Ih*Oj,nHuS43I)XVs(!qpV'Pf$,Nk6ZkhZZ'uBqhFV9/EHD.]<(i8&S+J&D>^McasA3.3+alnh9KI3%/djP",5L+(.C,ik-?p)YqA0#*bFH]YCtkD.!5Ab:ln[//PjEYgT6MR+k&8[T"gBfpk`N@auT>&Rcp!h86?;aZ$A4QFj#3A[9&c;T%1AkB9dfA%4MdR>fpQ?Cg4g^@71CQlDEKSZ4=p*!M]g/(8#\VY+TAeiU)okjN8M6HhY!Oht06#5N%~>endstream +endobj +22 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2399 +>> +stream +Gasaq@<:-n')h6*dAZY4X5M'YW&@e,>Cu.lgE@f4nbk7J%k_=>nR#jT^r[Xq&LBtahRq)_mO#/AOAH%"dsY$YO5fD#1nhl";J=s$0Y<[+Ea;]7dFi$VS"0,Q/t?$ms\8u4Y[g8T[M.ER80HYShAKHUf3$"8DMu\@WS2-L-A0dI"#E/L_V^fuDf%_DehS9*]gZO(C%W4Ll81,UU3:UZ\mb^p>Ag4$n*^9rd-L"+?$X1YP/i!c&-7I*uWM2MuQfK-oB0UHM/S9V*0M`:p9tl$C+'&#qYVX9^O>tPjnA;M4W8Ub@VnIp[SZiTF$l(KK@Z1+&Mc[5_5:5AD3?[o[/50JlD%;h&Q?"G9I*"?Ta])e+BL,"aO]@`qfK`%OTFE[_)cEo;2gW#dFU(C+HOa63n%#fkBdV3I!6t-iK*,AQT?2@G-(tf8Zk$ueV6dX#5%lr/m3u^pVCID"(m!&RoG2cKA=;N2L'Lu.*#Wg?Q_4?JN^Rk=j!Qi!>h9pJga*]*hLJ+*&LUcHC<(Bimm3nuaN$Xcg#Bs_%*rkqs4_B["HC(M1]6)7qR9[Q=loG,K3PkF2EN."]1i=ca%tFN;a3g3JZ^G^#!0Ec"i0!*h\VA$.:+KCj2.I"*0(So&GBa<(g8Q>Gnu!T`8!Fi.Ku(Njm6q;+pF$gd.%>V,'*mU3PmYuUM$$JBd7btaE260_;=P[,O?%J#FT`_.12)2bBYSEFH2JMboU$F^8:$_9&OFQgt$d&*@h*6?"%Op8R%P[,D!-0M\qfLa]9_5P2B[D=@>tq@M&:9"Uag&_'E5fa9DJUa>031_tbL3a_FP4NYK7Ko"cBEJJJ"DA,%j:*X3XB9MtHoCaaod^A@]B7B^m5')W")GAtVL4I1().J/'f[/Xf/b3"_E!iNYPgEOP0Lcuk.ml&R8bgrf_pY$'ML]P/$6=(g=L?;"L__b3AZF/-YSgSF/20l9K^c>@N\_[1'AgXa'!]KnSJ?eE'T]e]X4*]ICFs4g/2Ba,]=\FCuUNU?R);;.O3nfrUJ6r@lmT1@VZ"_>F*#i>1T.o?sAYJS*_G(%+RO<)e,(.qnN/b>5N?9r6`Ef]jkQW`d*A3jV=MI]i\Pd*eMA34ED=i,"mlVt,@63^2=XU1LVJM]='uHB],0?D/?BS%ADJY;KD7KhPjA-c>\--[X>CZ\Iq_*0&pW/KS#'mY\gtg5#;gdQ$k>Hpb7>1Rci;b-d$g^2bP%ig1P5h8V;mf_>01?YHp+dCMI:j+4$RYeW-A0KIP;>%GgN,_*B'qAs;IfTsjn4S69DcMf%8[.mSZGL3Y\RK\X*Rmr7#VT,4284#,u[5OP2jjpj2(?W.bp`&C-^endstream +endobj +23 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1452 +>> +stream +Gat%"D,91O&H9tY(g/n:\lVSS6>;QA*@D=?W&SZD\dqLM\W,(L8XsU'=J;bpI:o(G9:Nfc((iY%G[?teAfMaNph-)Z49G:n$n!tlfNf?k@%[!g(m!VDn^5s`C1fdN6f,#tq,t`Zp2/G(dfgbr/+)0a!UgNE#LKff4g8c?7pt/1:ddXfGmhVB(k3lTs.Z4`:qt3N_sYm+e'='LLA`8VGkBa#.fD>d7%R'?;5E3MA&NTYFeD7&aiqk$&'h]lB2Enk!WGQ9BfhX,7RAa0YlpQ6>.[og_@7bGc%UT]kZb;ib\>T;<[SPApk5C"WECBbn3j9a*D5^$f2jokX"Wo$oo7GSJ/8GZ,W3_q+,?F]l]i-&X>:u?A?B0\=ra+ZWa*E$an`6h!@gBB(ErmgZUmBRc(l+(bZ#u5OqB^>d/\a=nPSM\JsH*XAjRFM'OF$:LT#8m3\lnu(7kM0apPhtYk5(?.%_XCQ$h$ijsf$Y;isW[ODH#f"-'!9H6H=@XNVqn0pq&Xa=ug)`4;8Wd'4o2p(4PgYWJga7[(l0DWpJ:)]cWJW)0ea'Rjs[7_d&5[3;$DPu0Cro<1"!;8.o&Ae15[Df"^GbcYmVnLOuHmT@\%2^]WqO8K+."_nPiWA0=1aJEB0rGsi2KC-%CmDIf5n/;4@6an%ijj<%#jhrc!dfqMEg+@$N*,\3B6F^%kT>=#GhT$d+XVcWl';(Eb3nQ,"8jICO5FF*H=%"3H2N7M=9:lqbOWm*B`MV4t?BR+.@QFgm(VJoQd'$`M).cDW$efsAJ,XK]n/bE('i6bEbt7@Xb]ME,^ag&-mSd+iC7@\;(i=*!m#(FCCWHDtdTfcZF"0,"p_P!WehfZ&Vg09JmWQ9D)AR2G;1L9S3?_FYosSlHS%=rJN*/9U'S3^9hj`iQ&D3:+P.)?U5top;$bq\"L0=_*G7JHq3'(nrmi8[._%*:K!("R1JJDDOCQ69IJ;6CD'[Olp94ZP=crU%"$FS%.6MXFTn1uhkP+pB5>iB<0=#KPHi",8(u<8nUIQMb9`u[qla^-HY/oFL-_C@Xhtl4s1:f),k.5MW$-[N:TsX-k?#%gI>Go]#.3*a@Ke=$_~>endstream +endobj +xref +0 24 +0000000000 65535 f +0000000061 00000 n +0000000112 00000 n +0000000219 00000 n +0000000331 00000 n +0000000536 00000 n +0000039159 00000 n +0000039515 00000 n +0000039783 00000 n +0000039988 00000 n +0000040093 00000 n +0000040299 00000 n +0000040505 00000 n +0000040711 00000 n +0000040917 00000 n +0000040987 00000 n +0000041273 00000 n +0000041373 00000 n +0000044102 00000 n +0000046216 00000 n +0000047533 00000 n +0000049857 00000 n +0000052171 00000 n +0000054662 00000 n +trailer +<< +/ID +[<53604fe014ae60477ed87cbc6421488e><53604fe014ae60477ed87cbc6421488e>] +% ReportLab generated PDF document -- digest (opensource) + +/Info 15 0 R +/Root 14 0 R +/Size 24 +>> +startxref +56206 +%%EOF diff --git a/lab_rag/Penjelasan_Hasil_Lab1.docx b/lab_rag/Penjelasan_Hasil_Lab1.docx new file mode 100644 index 0000000..3ebc370 Binary files /dev/null and b/lab_rag/Penjelasan_Hasil_Lab1.docx differ diff --git a/lab_rag/Penjelasan_Hasil_Lab2.docx b/lab_rag/Penjelasan_Hasil_Lab2.docx new file mode 100644 index 0000000..f818d23 Binary files /dev/null and b/lab_rag/Penjelasan_Hasil_Lab2.docx differ diff --git a/lab_rag/Penjelasan_Hasil_Lab3.docx b/lab_rag/Penjelasan_Hasil_Lab3.docx new file mode 100644 index 0000000..f2a5f0a Binary files /dev/null and b/lab_rag/Penjelasan_Hasil_Lab3.docx differ diff --git a/lab_rag/README.md b/lab_rag/README.md new file mode 100644 index 0000000..fc19c10 --- /dev/null +++ b/lab_rag/README.md @@ -0,0 +1,15 @@ +# Lab RAG: Chunking, Indeks, dan Hit@k + +Jalankan dari dalam folder ini: + + pip install pdfplumber scikit-learn numpy matplotlib reportlab pillow + python buat_dokumen_contoh.py # opsional: buat 3 PDF contoh di dokumen/ + python lab1_chunking.py # -> Lab1_Eksperimen_Chunking.pdf + python lab2_indeks_cari.py # -> Lab2_Indeks_dan_Pencarian.pdf + python lab3_hit_at_k.py # -> Lab3_Hit_at_k.pdf + +Untuk memakai PDF sendiri: taruh di dokumen/, lalu ubah PDF di lab1, PERTANYAAN/PARAFRASE di lab2, +dan SOAL (15 pertanyaan + kata kunci) di lab3. + +Embedding: otomatis memakai sentence-transformers (paraphrase-multilingual-MiniLM-L12-v2) bila terpasang; +jika tidak, memakai LSA (TF-IDF n-gram karakter + SVD) yang berjalan offline. diff --git a/lab_rag/__pycache__/laporan_utils.cpython-313.pyc b/lab_rag/__pycache__/laporan_utils.cpython-313.pyc new file mode 100644 index 0000000..3f3458f Binary files /dev/null and b/lab_rag/__pycache__/laporan_utils.cpython-313.pyc differ diff --git a/lab_rag/__pycache__/rag_utils.cpython-313.pyc b/lab_rag/__pycache__/rag_utils.cpython-313.pyc new file mode 100644 index 0000000..755748f Binary files /dev/null and b/lab_rag/__pycache__/rag_utils.cpython-313.pyc differ diff --git a/lab_rag/buat_dokumen_contoh.py b/lab_rag/buat_dokumen_contoh.py new file mode 100644 index 0000000..fd9e605 --- /dev/null +++ b/lab_rag/buat_dokumen_contoh.py @@ -0,0 +1,144 @@ +"""Membuat 3 PDF contoh (bahasa Indonesia) di folder dokumen/. + +Jika Anda sudah punya PDF sendiri, cukup letakkan di folder dokumen/ dan +lewati skrip ini. Skrip ini hanya agar seluruh lab bisa dijalankan langsung. +""" +import os +from xml.sax.saxutils import escape +from reportlab.lib.pagesizes import A4 +from reportlab.lib import colors +from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle +from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle + +BASE = os.path.dirname(os.path.abspath(__file__)) +FOLDER = os.path.join(BASE, "dokumen") + +DOKUMEN = { +"pengantar_rag.pdf": { + "judul": "Pengantar Retrieval-Augmented Generation (RAG)", + "bagian": [ + ("1. Pengertian RAG", [ + "Retrieval-Augmented Generation (RAG) adalah arsitektur yang menggabungkan pencarian dokumen dengan model bahasa besar. Model tidak hanya mengandalkan pengetahuan hasil pelatihan, tetapi juga menerima potongan dokumen yang relevan sebagai konteks tambahan saat menjawab pertanyaan.", + "Pendekatan ini diperkenalkan oleh Lewis dan kawan-kawan pada tahun 2020 di Facebook AI Research. Tujuannya adalah mengurangi halusinasi dan memungkinkan jawaban bersumber dari dokumen terbaru tanpa harus melatih ulang model dari awal."]), + ("2. Alur Kerja RAG", [ + "Sistem RAG terdiri dari dua tahap, yaitu tahap pengindeksan yang berjalan offline dan tahap penjawaban yang berjalan online. Pada tahap pengindeksan, dokumen dibaca, dipotong menjadi chunk, diubah menjadi vektor embedding, lalu disimpan dalam vector store.", + "Pada tahap penjawaban, pertanyaan pengguna diubah menjadi vektor dengan model embedding yang sama. Sistem lalu mengambil k chunk yang paling dekat dengan vektor pertanyaan dan menyisipkannya ke dalam prompt untuk model bahasa."]), + ("3. Embedding dan Kemiripan", [ + "Embedding adalah representasi teks berupa vektor bilangan real dengan dimensi tetap. Model MiniLM menghasilkan embedding 384 dimensi, sedangkan model berbasis BERT-base menghasilkan 768 dimensi. Teks dengan makna mirip akan menghasilkan vektor yang berdekatan.", + "Kemiripan antar vektor biasanya diukur dengan cosine similarity, yang bernilai antara -1 dan 1. Semakin mendekati 1, semakin searah kedua vektor tersebut. Pencarian semantik tetap dapat menemukan dokumen walaupun kata dalam pertanyaan berbeda dari teks, misalnya pertanyaan tentang kendaraan roda empat yang cocok dengan dokumen tentang mobil."]), + ("4. Chunking", [ + "Chunk yang terlalu kecil kehilangan konteks, sedangkan chunk yang terlalu besar mencampur beberapa topik sehingga skor kemiripannya menjadi encer. Praktik yang umum adalah ukuran 500 sampai 1000 karakter dengan overlap 10 sampai 20 persen.", + "Overlap mencegah informasi penting terpotong tepat di batas antar chunk. Pemotongan berbasis kalimat atau paragraf lebih rapi daripada pemotongan karakter murni, tetapi ukuran chunk menjadi tidak seragam. Tabel perlu diperlakukan khusus karena baris tabel kehilangan makna bila terpisah dari baris judul kolomnya."]), + ("5. Vector Store", [ + "Vector store menyimpan embedding dan mendukung pencarian tetangga terdekat. FAISS adalah pustaka buatan Meta untuk pencarian tetangga terdekat yang sangat cepat. ChromaDB menyimpan embedding bersama metadata seperti nama file dan nomor halaman, sedangkan Qdrant menyediakan layanan server tersendiri.", + "Untuk koleksi besar, banyak vector store memakai indeks HNSW yang mencari tetangga terdekat secara aproksimasi demi kecepatan, dengan sedikit pengorbanan akurasi."]), + ("6. Evaluasi Retrieval", [ + "Hit@k adalah proporsi pertanyaan uji yang jawaban benarnya muncul di antara k chunk teratas. Sebagai contoh, bila 12 dari 15 pertanyaan terjawab pada lima chunk teratas, maka Hit@5 bernilai 0,8. Metrik lain yang sering dipakai adalah MRR dan Recall@k.", + "Disarankan menyiapkan minimal 15 sampai 30 pertanyaan uji lengkap dengan kata kunci jawaban. Bandingkan beberapa pengaturan chunk pada pertanyaan yang sama agar perbedaannya adil."]), + ("7. Halusinasi dan Sitasi", [ + "Halusinasi adalah keluaran model yang terdengar meyakinkan tetapi tidak didukung fakta. RAG mengurangi halusinasi, tetapi tidak menghilangkannya sepenuhnya, terutama bila chunk yang diambil tidak relevan.", + "Sistem yang baik menampilkan sumber berupa nama file dan nomor halaman sehingga pengguna dapat memeriksa jawaban. Bila chunk teratas tidak relevan, model sebaiknya menjawab bahwa informasi tidak ditemukan daripada mengarang."]), + ], + "tabel": {"setelah_bagian": "4. Chunking", + "caption": "Tabel 1. Perbandingan ukuran chunk", + "data": [["Ukuran", "Kelebihan", "Kekurangan", "Cocok untuk"], + ["500 karakter", "Presisi tinggi, hemat token", "Konteks sempit, kalimat sering terpotong", "FAQ dan pertanyaan faktual singkat"], + ["1000 karakter", "Seimbang antara konteks dan presisi", "Kadang memuat dua topik", "Dokumen laporan umum"], + ["1500 karakter", "Konteks luas", "Skor encer dan boros token", "Dokumen naratif panjang"]]}, +}, +"machine_learning_dasar.pdf": { + "judul": "Dasar-Dasar Machine Learning", + "bagian": [ + ("1. Supervised Learning", [ + "Pada supervised learning, model belajar dari data yang sudah berlabel. Tugas klasifikasi memprediksi kategori, misalnya menandai surel sebagai spam atau bukan spam. Tugas regresi memprediksi nilai kontinu, misalnya harga rumah berdasarkan luas dan lokasi."]), + ("2. Pembagian Data", [ + "Data biasanya dibagi menjadi data latih 70 persen, data validasi 15 persen, dan data uji 15 persen. Data validasi dipakai untuk menyetel hiperparameter, sedangkan data uji hanya dipakai satu kali di akhir untuk menilai performa akhir. Data uji tidak boleh dipakai saat tuning karena akan menyebabkan kebocoran informasi."]), + ("3. Overfitting dan Underfitting", [ + "Overfitting terjadi ketika model sangat baik pada data latih tetapi buruk pada data baru. Cirinya adalah selisih besar antara akurasi latih, misalnya 99 persen, dan akurasi validasi, misalnya 72 persen. Model seolah menghafal data latih, termasuk derau di dalamnya.", + "Underfitting terjadi ketika model terlalu sederhana sehingga akurasi latih maupun validasi sama-sama rendah. Cara mengatasi overfitting antara lain regularisasi, early stopping, dropout pada jaringan saraf, dan menambah jumlah data."]), + ("4. Cross-Validation", [ + "Cross-validation menilai model secara lebih stabil daripada satu kali pembagian data. Pada k-fold cross-validation, data dibagi menjadi k lipatan dan setiap lipatan bergantian menjadi data validasi. Nilai k yang lazim adalah 5 atau 10.", + "Untuk kelas yang tidak seimbang, gunakan stratified k-fold agar proporsi kelas pada tiap lipatan tetap terjaga."]), + ("5. Metrik Klasifikasi", [ + "Akurasi menghitung proporsi prediksi yang benar, tetapi menyesatkan bila kelas tidak seimbang. Precision mengukur seberapa banyak prediksi positif yang benar, sedangkan recall mengukur seberapa banyak data positif yang berhasil ditemukan.", + "F1-score adalah rata-rata harmonik dari precision dan recall sehingga nilainya rendah bila salah satunya rendah. Untuk deteksi penyakit, recall diutamakan karena melewatkan pasien jauh lebih berbahaya daripada alarm palsu. Untuk filter spam, precision diutamakan agar surel penting tidak terbuang."]), + ("6. Gradient Descent", [ + "Gradient descent adalah algoritma optimasi iteratif yang memperbarui parameter ke arah berlawanan dengan gradien fungsi kerugian. Learning rate yang terlalu besar membuat pelatihan divergen, sedangkan yang terlalu kecil membuat pelatihan sangat lambat.", + "Pada mini-batch gradient descent, gradien dihitung dari sebagian kecil data, biasanya berukuran 32 atau 64 sampel per langkah."]), + ("7. Decision Tree dan Random Forest", [ + "Decision tree membagi data berdasarkan fitur dengan kriteria Gini impurity atau entropi. Pohon yang terlalu dalam cenderung overfitting. Random forest menggabungkan banyak pohon yang dilatih pada sampel acak berbeda (bagging) lalu mengambil suara terbanyak, sehingga variansi prediksi menurun."]), + ("8. Regularisasi", [ + "Regularisasi L1, atau Lasso, mendorong sebagian bobot menjadi tepat nol sehingga berfungsi sebagai seleksi fitur. Regularisasi L2, atau Ridge, mengecilkan bobot tanpa menjadikannya nol. Kekuatan regularisasi diatur oleh hiperparameter lambda."]), + ], + "tabel": {"setelah_bagian": "5. Metrik Klasifikasi", + "caption": "Tabel 1. Ringkasan metrik klasifikasi", + "data": [["Metrik", "Rumus", "Dipakai ketika"], + ["Akurasi", "(TP+TN)/(TP+TN+FP+FN)", "Kelas seimbang"], + ["Precision", "TP/(TP+FP)", "Biaya false positive tinggi"], + ["Recall", "TP/(TP+FN)", "Biaya false negative tinggi"], + ["F1-score", "2*P*R/(P+R)", "Kelas tidak seimbang"]]}, +}, +"etika_keamanan_ai.pdf": { + "judul": "Etika dan Keamanan Kecerdasan Buatan", + "bagian": [ + ("1. Bias pada Data", [ + "Model kecerdasan buatan mewarisi bias yang ada pada data latihnya. Contoh yang sering dikutip adalah sistem seleksi pelamar kerja milik Amazon yang dihentikan pada tahun 2018 karena cenderung merendahkan pelamar perempuan, akibat dilatih dengan data riwayat perekrutan yang didominasi laki-laki.", + "Mitigasi bias mencakup audit dataset, pengukuran metrik kewajaran antar kelompok, serta pengujian model pada subkelompok yang berbeda sebelum digunakan."]), + ("2. Privasi dan Pelindungan Data Pribadi", [ + "Di Indonesia, pelindungan data pribadi diatur dalam Undang-Undang Nomor 27 Tahun 2022 tentang Pelindungan Data Pribadi. Prinsip pentingnya adalah minimisasi data, persetujuan yang eksplisit dari pemilik data, serta hak subjek data untuk mengakses dan meminta penghapusan datanya.", + "Anonimisasi menghapus identitas secara permanen, sedangkan pseudonimisasi hanya mengganti identitas dengan kode yang masih dapat ditelusuri kembali. Keduanya mengurangi risiko, tetapi hanya anonimisasi yang benar-benar melepaskan data dari pemiliknya."]), + ("3. Transparansi dan Keterjelasan", [ + "Model kotak hitam sulit dijelaskan kepada pengguna yang terdampak keputusannya. Teknik seperti LIME dan SHAP memperkirakan seberapa besar kontribusi tiap fitur terhadap satu prediksi. Keterjelasan penting pada bidang berisiko tinggi seperti kredit, kesehatan, dan hukum."]), + ("4. Serangan Adversarial", [ + "Serangan adversarial mengubah input sedikit saja, sering kali dengan derau yang tidak terlihat oleh mata, sehingga model salah mengklasifikasi. Contoh terkenal adalah stiker kecil pada rambu stop yang membuat model penglihatan komputer membacanya sebagai rambu batas kecepatan. Pertahanan yang umum adalah adversarial training, yaitu melatih model dengan contoh serangan."]), + ("5. Prompt Injection", [ + "Prompt injection adalah serangan berupa instruksi berbahaya yang disisipkan dalam masukan pengguna atau dalam dokumen, dengan tujuan membajak perilaku model. Risikonya besar pada sistem RAG karena dokumen yang diambil diperlakukan sebagai konteks tepercaya.", + "Mitigasinya antara lain memisahkan instruksi sistem dari data, menyaring keluaran model, dan menerapkan hak akses minimum pada alat yang dapat dipanggil model."]), + ("6. Tata Kelola dan Akuntabilitas", [ + "Tata kelola yang baik mencakup audit berkala, keterlibatan manusia dalam pengambilan keputusan penting (human in the loop), dan pencatatan log keputusan. Dokumentasi model dalam bentuk model card diperkenalkan oleh Mitchell dan kawan-kawan pada tahun 2019 untuk menjelaskan tujuan, data, dan batasan sebuah model.", + "Akuntabilitas tetap berada pada manusia dan organisasi yang menerapkan sistem, bukan pada model itu sendiri."]), + ], + "tabel": {"setelah_bagian": "5. Prompt Injection", + "caption": "Tabel 1. Ringkasan risiko dan mitigasi", + "data": [["Risiko", "Contoh", "Mitigasi"], + ["Bias", "Seleksi otomatis menolak kelompok tertentu", "Audit dataset"], + ["Kebocoran data", "Model mengungkap data pribadi", "Anonimisasi"], + ["Serangan adversarial", "Stiker pada rambu stop", "Adversarial training"], + ["Prompt injection", "Instruksi tersembunyi di dokumen", "Pisahkan instruksi dari data"]]}, +}, +} + + +def buat_pdf(nama_file, isi): + st = getSampleStyleSheet() + judul = ParagraphStyle("j", parent=st["Title"], fontSize=18, spaceAfter=14) + h = ParagraphStyle("h", parent=st["Heading2"], fontSize=13, spaceBefore=10, spaceAfter=4) + p = ParagraphStyle("p", parent=st["BodyText"], fontSize=10.5, leading=15, spaceAfter=6) + cap = ParagraphStyle("c", parent=p, fontName="Helvetica-Bold", spaceBefore=6, spaceAfter=3) + sel = ParagraphStyle("s", parent=p, fontSize=9, leading=11, spaceAfter=0) + doc = SimpleDocTemplate(os.path.join(FOLDER, nama_file), pagesize=A4, + leftMargin=60, rightMargin=60, topMargin=60, bottomMargin=60, + title=isi["judul"]) + cerita = [Paragraph(escape(isi["judul"]), judul)] + t = isi["tabel"] + for nama, paragraf in isi["bagian"]: + cerita.append(Paragraph(escape(nama), h)) + for kal in paragraf: + cerita.append(Paragraph(escape(kal), p)) + if nama == t["setelah_bagian"]: + cerita.append(Paragraph(escape(t["caption"]), cap)) + data = [[Paragraph(escape(c), sel) for c in baris] for baris in t["data"]] + tb = Table(data, hAlign="LEFT") + tb.setStyle(TableStyle([("GRID", (0, 0), (-1, -1), 0.5, colors.grey), + ("BACKGROUND", (0, 0), (-1, 0), colors.lightgrey), + ("VALIGN", (0, 0), (-1, -1), "TOP")])) + cerita.append(tb) + cerita.append(Paragraph("Sumber: ringkasan penulis.", p)) + doc.build(cerita) + + +if __name__ == "__main__": + os.makedirs(FOLDER, exist_ok=True) + for nama, isi in DOKUMEN.items(): + buat_pdf(nama, isi) + print("dibuat:", os.path.join("dokumen", nama)) diff --git a/lab_rag/dokumen/1_Pengenalan_Kecerdasan_Buatan.pdf b/lab_rag/dokumen/1_Pengenalan_Kecerdasan_Buatan.pdf new file mode 100644 index 0000000..295e756 --- /dev/null +++ b/lab_rag/dokumen/1_Pengenalan_Kecerdasan_Buatan.pdf @@ -0,0 +1,99 @@ +%PDF-1.4 +%東京 ReportLab Generated PDF document (opensource) +1 0 obj +<< +/F1 2 0 R /F2 3 0 R /F3 4 0 R +>> +endobj +2 0 obj +<< +/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font +>> +endobj +3 0 obj +<< +/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font +>> +endobj +4 0 obj +<< +/BaseFont /Helvetica-Oblique /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font +>> +endobj +5 0 obj +<< +/Contents 10 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 9 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +6 0 obj +<< +/Contents 11 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 9 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +7 0 obj +<< +/PageMode /UseNone /Pages 9 0 R /Type /Catalog +>> +endobj +8 0 obj +<< +/Author (Claude) /CreationDate (D:20261102024209+00'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20261102024209+00'00') /Producer (ReportLab PDF Library - \(opensource\)) + /Subject (\(unspecified\)) /Title (Pengenalan Kecerdasan Buatan) /Trapped /False +>> +endobj +9 0 obj +<< +/Count 2 /Kids [ 5 0 R 6 0 R ] /Type /Pages +>> +endobj +10 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2022 +>> +stream +Gatm<968iG&AJ$ClqtmW%)Fld6cX'_=,rhCCJALPI25_+hA+,)b'h,P=Y%QG3%t0i+0`$uG4QcmP2_\COj=Tp!L0(KPL!2kiOUq5q!oNZJ`'#&e\)6]8_I=#HK,?/kp7o\0b6pK5[7E1Y,fI;j%QFJs^-/>k,cZXp\?h6Io6#$.n3Dk"Q'WAbMnoIor!Sb;r,R&[UE,i\59B[Om!`#_CfpYb<<]p\?FI80QpD&Otuj\bNnH)C#i1o29Wdea'7:*u`B%mln;N'J%R\O(($$S!WD8T,kW,iMbd6+ZQ))b7hmb#?4?ILKF%\-+Te^[K>oNd-:Y1b.`)HdQ`[c)Di44LiIagp0]D.^HkP5gECZC-]On!X`+]hWD,L\R9ke7pAUumi/Ch"L[YSR_SGic5*=1_n5%`SUQUFdFc9@t/)>W7gnEBOM($7cO\Ud-,DR?Bd!:Arm;UM/R**:VLY::24A0ETEL"B.+$KWShMEC@3LR)S3pVGa3(81b5;s_38q%j!D[DQ/5G\jZD;01F\USQ+RhH!=<*kW6%R&ra2L=7YhcN#9='OgJ>]ltP?t:Q[QW:'#2L=NAmsVO@)\^U`t]uR!^76luhbOE1lq;)RK$.cZV*Qq`ngt\0_d$$73k`lubJ/@dcd8F?XoM!m_jjIlDCRI^_ZQ(`N*E^$3_bn,f[%p2Sb'#3c0>/D/)AR_Zp2.nPF:l`71rWE9g2YC>%kUJi@/b'kloe/qB7X^r#9W3]GYQ"kf+U\8#5QM/-$g94UsF):ZRq$suW?YuJiWZOKL-%4UFmF.MG]++8r&Mmg4S7.0!^-\l-;150W-eO+*4)E=L_TF:pQ;OlAr%1c1oieWpf\s'K(Ynf"cjEuYb0bSV6sBq%d/lS@IHpf"Tkt!bl].E"%fd6H7Uq^)?aW2pt0YaB(Zu\u8l@X>(:Q^.R`Csp#fFa&g,4"_VAgn4/W:g*PKe`[Cb^HR,6?0)KD'gX96\=V<7];C)E);u(_b6ohVBta^#m#XQd,)*dL06#'`m]f^)L'+g,i6dYQ+i3%1fcFrLCtZ^^Yh+tIYF-!<)N\XcP;%lK,[C$g6jQ-m/ls<7m/m]ump)EW.4PVeDCf'R;3n8\,9Ol(3QF+=,>]HR>MC\9pnm[:>nA/u<[?%F+CdQ[I2YWVN0[U1@TYQqa>PXuU('a_R>/gUXS^Bi*dDN&T^O,j$p2iifPL)_V*np*T#&~>endstream +endobj +11 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1892 +>> +stream +GauHL?$G!^&:Mm.Qq,ko\sC+EDf'^qYt]SnK^McG"=Q_Vb?e=h:B(2uad>2MBZ,hi:HpN7Aci-(3p#N9npTdeS(],aZ(d7fKKq6%\ie')]ZHNh.N'*`OBh[QE7N_Gh='SVlK#S0:^U3RG@B![9aumbf@S4P^9Ca3\MS1@SLkGhA76-oeVcmICoA)nQ2#>&:e;8tINJT2jc")YOs8%./N7n%$1Z*SSmoK5?5*^>%$o3?K9e*4W3Kht_g.2k`,8Nf%+j$Le*HhraK&)1P=)bhY;4?J6G)`"T6N4Dp>aNfcau'D>^#819T3K5A3#GI=@`D((HaVcsm7rOq[?hJp@h&lkd/]7goGD%StZnL"j;aW]3*9gi*F=riO$c066WnK0!AS$;=*.8%.2:,9&pr\(Y*;8GRe\G;GM)8>S3QdDgr4<33lKSp;UokBJ'X:LTj1eNg%mar9e6ntEB9aA9CkA??MPB>+43PgKhVo`clEWWbX87a@fS<-LD2beV>q6U>'h,XmQRVD(b),FnqLIrmkk7A)P@g4b@LdhX!RMh1_lAfnJS8Kjq^BK@\D#K"KE]f$Jt']?u2\d"1Jmd=G?U_-#@eaD/G,%%;\#a2*?Y4j:`oR/JWIQ?Ze@Xi0aBGp(bj/$gh-[3t+bFjN-Dg@O"QA$MY\M7_OCbH$:#]FH@.!P;pFgnf%@1moaQ@t+,\f!Lds2t;7L>)M>bVpQ9R^s892k6ACkF8M.q*Zi[Bl@3JUojb,=18+^g:Mbf;i9OKAp"s/Sgg=S5mr.b-c8*6]!FCh6H$e?6YHE"CC*dk~>endstream +endobj +xref +0 12 +0000000000 65535 f +0000000061 00000 n +0000000112 00000 n +0000000219 00000 n +0000000331 00000 n +0000000446 00000 n +0000000650 00000 n +0000000854 00000 n +0000000922 00000 n +0000001210 00000 n +0000001275 00000 n +0000003389 00000 n +trailer +<< +/ID +[<7d7f044912e8cefa8327dfcaf4312ec8><7d7f044912e8cefa8327dfcaf4312ec8>] +% ReportLab generated PDF document -- digest (opensource) + +/Info 8 0 R +/Root 7 0 R +/Size 12 +>> +startxref +5373 +%%EOF diff --git a/lab_rag/dokumen/2_Machine_Learning_dan_Deep_Learning.pdf b/lab_rag/dokumen/2_Machine_Learning_dan_Deep_Learning.pdf new file mode 100644 index 0000000..0fdd824 --- /dev/null +++ b/lab_rag/dokumen/2_Machine_Learning_dan_Deep_Learning.pdf @@ -0,0 +1,99 @@ +%PDF-1.4 +%東京 ReportLab Generated PDF document (opensource) +1 0 obj +<< +/F1 2 0 R /F2 3 0 R /F3 4 0 R +>> +endobj +2 0 obj +<< +/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font +>> +endobj +3 0 obj +<< +/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font +>> +endobj +4 0 obj +<< +/BaseFont /Helvetica-Oblique /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font +>> +endobj +5 0 obj +<< +/Contents 10 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 9 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +6 0 obj +<< +/Contents 11 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 9 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +7 0 obj +<< +/PageMode /UseNone /Pages 9 0 R /Type /Catalog +>> +endobj +8 0 obj +<< +/Author (Claude) /CreationDate (D:20261102024209+00'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20261102024209+00'00') /Producer (ReportLab PDF Library - \(opensource\)) + /Subject (\(unspecified\)) /Title (Machine Learning dan Deep Learning) /Trapped /False +>> +endobj +9 0 obj +<< +/Count 2 /Kids [ 5 0 R 6 0 R ] /Type /Pages +>> +endobj +10 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1762 +>> +stream +GauHK>Bed\&:Vs/Qq,Rl<69@Q>M3ee_hKK76e@N[;rUWnTV8llj8W!M^St?V2X&>&^U>8mm4#57"N30f'T.cu7TA[[)6U&>S^!\=m+/LFo0:hh%W9C;-eR?,3NFb\)SuFJEmKSnehH.&DN`aS:X.Zp@@_Wq[@lcC+VbI6[XP7gH/gRJ!mr;2uKEkK_o*K44^?DV>P4B[dU6@3Kr3nn>F:UL"aHAFrdsdE0S)>.rLHQ>m&VdEV@V*;BRkF9u`V(*Z1k.Cf9l((r<83M]*XXt-2-YHEeBDdT9PW#Ep6:6@"V?J:X7EV77KMeifE?K_*>K'Z&SaqUu-%u&;+DQs`jGs)q7f?]0%]0em;]!dG%M(i9VcN:f(C5lik't:F*k5$`Q5==o&67"Mc3(jj5"+3.M/0ROT9"AaDb&BO9^@(U'e+4T8+D=!6&SleJ1V%n_E/,mJO9rqucFD&p-s(bh"TAU_'7*/7;`&l%aA,\'^/.h7gn+f_dt8IJ]?bo!pGH!4T<]/hf5#ZpT.iC'L]rF"hE>dc=FPD40uc\=T;\^P\R\:I92X&X*_\`G`OY+>YFt4k19@a5G#3"^R]^6)G!n#Z_K7FD/C0T<`>Z'O-&H?6$W2b0,e,=Em#QprE3Q\9;>sQdKl(oa%"o:gE/Mra6u6MJ9K\cC6Ki\Lj/*u/#O>ZO,uuZ=BhTmYeg]aT3[+t`qXp$@MVYA''&a0J3sl!&QK5.2_Q:-AqJ[05h_4T[f)"K^'HE/h0k@B7VkU"9(nd(>(!rak!6huqoqXiPLVh_eED">7$Vd'CN>_@E?ubcpe,-FMjtJS):n6\F@>h;#?m"L9Mde,#;_Tp:\ULGFr[4UJeN'CTD)EUSGeB78Mi'FkG==%+=V8uAfPAl8=BE"Ba$f+[je4h3)/L"`[2f[r(i9"W3((1JmhM+j0Miq`;"j/Fd+q&,_%(.A^8S4$L#@@(V54e@U9e\h$s[UZhs2Mg[Y8n$"!P-;srr1(/kY_%(APMb?:N3`-ZWRHPBeQromCo]!r>WQ-HUL(>VAh\CVM\@+rl3]#=;+YV@52hTh;U8'LkS%9PEWi7S#/Q.5K"@7oIDSUhF(A"hA8N2'.O(rP$VV,FFm~>endstream +endobj +11 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1870 +>> +stream +GauHL>BeOU&:X)OR)cuk`q%sT<1pHHD7@m]eebko'%N=nA\!ME^RsRHERL]j4Y.tY9q7>X1q-9(Pub97[bf/<(K`^T3dU_3XB"3-:>%ouR^aQ\BEMj,ul]nUd+?,4>\pDe]-tkkb]crN;MJd$97u#Dj+j?A]solnFKS;+cl;L.UBe'?!2HD:,3$fQdAB,8Q\'H_*7f-ueC&&2g!bXt!T!2G?>M4Gnp62b\n=Z/IcN_YaP!\[T#m@+?XEN)eKDe;Qj-XkH%p%b/"Rt\[p3>p4u?O7.;>bb4A:G(Y4ogkVf4se9"G+a11'q?3>K2m%Bgb_&mFk;Itms.('QXs8VpW-7T>g8OsXH*jUl_i/)j^,(!kc8M1#PLDHLF'RCW^2->Rin1L=Zu*NonAHX9fm7)]O*>1@REeAd:>5b-dID17FB<;iO#HR#-.V&F/PA@Eb\u:K@!=+]Z4=qV#;p5g8?o(#>>!Y0YLg&U7(>lup,kEqFB;a,Brs'Y=?'<5'72@q0LTsX(U]WjXpKG'aA3@a)=cNL(B@8:!^(T,Q39+ejq.LSrX<.X;2`e.haM`if!X?oSD2)X+.-4`u=tqN&#nU:P)hrjrh=&nT@"0,H[E'Bo$@s`G15,#V+Eo]GPXGB?UHe/'QPO*@r6j`dTn@./R7RlBbnk[,/B,(MkjAR9[Lj-;e.H2$[5,BSn!2W%*9&r9s1%)51Z['&B3D]u@dhIC]ikh!8"NrFhl"Zd(3i7oe4b&UC#l@Y;[Msprqbl>&a',bpG4E,KlKHN9\SPioJRMA6YhGglhA=k8B#U9_C1(S1m,6IWQ%?bHF22KcW6gBi&D\cQn).Y);)E>UT%[,h!S@hq2D#01Ci;'&Xp#NIY7MsXBW',ou!X1.,XTP8Prmt=^-32%k!udO/pDC4>XHI,E&[dSiND.YC8el=GO2a9Ra5IUdZ4klT;bk-+M/r[Hhk<5ggrUe6I2^+Gd.klY=>?\e,;6gWgi\rendstream +endobj +xref +0 12 +0000000000 65535 f +0000000061 00000 n +0000000112 00000 n +0000000219 00000 n +0000000331 00000 n +0000000446 00000 n +0000000650 00000 n +0000000854 00000 n +0000000922 00000 n +0000001216 00000 n +0000001281 00000 n +0000003135 00000 n +trailer +<< +/ID +[<239e77dec8ec83432ff71eda0a1f8199><239e77dec8ec83432ff71eda0a1f8199>] +% ReportLab generated PDF document -- digest (opensource) + +/Info 8 0 R +/Root 7 0 R +/Size 12 +>> +startxref +5097 +%%EOF diff --git a/lab_rag/dokumen/3_Etika_Risiko_dan_Masa_Depan_AI.pdf b/lab_rag/dokumen/3_Etika_Risiko_dan_Masa_Depan_AI.pdf new file mode 100644 index 0000000..e6173ca --- /dev/null +++ b/lab_rag/dokumen/3_Etika_Risiko_dan_Masa_Depan_AI.pdf @@ -0,0 +1,99 @@ +%PDF-1.4 +%東京 ReportLab Generated PDF document (opensource) +1 0 obj +<< +/F1 2 0 R /F2 3 0 R /F3 4 0 R +>> +endobj +2 0 obj +<< +/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font +>> +endobj +3 0 obj +<< +/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font +>> +endobj +4 0 obj +<< +/BaseFont /Helvetica-Oblique /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font +>> +endobj +5 0 obj +<< +/Contents 10 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 9 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +6 0 obj +<< +/Contents 11 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 9 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +7 0 obj +<< +/PageMode /UseNone /Pages 9 0 R /Type /Catalog +>> +endobj +8 0 obj +<< +/Author (Claude) /CreationDate (D:20261102024209+00'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20261102024209+00'00') /Producer (ReportLab PDF Library - \(opensource\)) + /Subject (\(unspecified\)) /Title (Etika, Risiko, dan Masa Depan AI) /Trapped /False +>> +endobj +9 0 obj +<< +/Count 2 /Kids [ 5 0 R 6 0 R ] /Type /Pages +>> +endobj +10 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1949 +>> +stream +GatmP!.fb)^k,hh$2_:`Lu'cJo`me"UW!\!^^4]E2n`R'r4!SE'"d'_o3oHA?'.O,*kn,.:P_$OC@"#;Wg&"f_nrg`O7VC6tX^UU^Ca?\m2*SbM1g9lns.$dD@8$Q0E4)pQp8n3Ki=Hq[CJ!+'n0`W]AZO#HO$-#R2It-tY$HLTf8h<"$1#*W'o.h8-HR5=^8'@oBiJeH2l_t-0%ib&1@WtcnHiRR?/)V7n)68V<5CJ^DPINrm2?F]1^YU64W<^nA.Mj1J"Bao[47HhKs\*>[l@9d!fAga@FSJi4h0'HVIe\8G+jYGheNrc\@dZ8KWTf.^s3nj%U["Un;"$jC=mAX"o8q0^'S($gJunUd.(X[1RJ]#3!>02CpsH=d8OOO%0f_f:]#br\YnmVdGY1BoTi6<$KeEpMIn[.0IoLIT4i:ep3co$o>DG&56V%YReKRLCtVUf.E&n*hhE!<4W78X+o+HXlWKB:%_!p#>!!34'(aS:0JUGIjL8;N6NT.`&lk:(d?!0O+=nm^M?UFdH<]_OYJ;QQWPaGFK"Z+QGp0VIWn^3B[([1Y+RVR]n\S=/M^%eCSkm*G.oA>c96ZtT51SoGIG";@[FB*"!a]rT"%QTl:oipX^#ThQ-J>*O5jjr^uQL94X;m7)tsEb"2?ZBfJ`F/W.j$W9S(NS"i[H=(/Yo2h$7!]?$TA:iiF[:7'GRbc$O_?q4eO@o-[/@2aFt39U&B'VHS0]=POD8("u@=X.7&n-:\S[8Q[Wbgc.\."6>R1Bo;9X>X(H?GDkT2=uI0&U\aW=lrNSf127V9%WJ#RQ`at,Y&r3$SZSH9b\6^_k\?B?KO[jmVRTg)6Emc/nHMZ7\)YO4AJPJ]":U[*1'LDG#n)h0)0efoLJ5#8GYl_p!^flrRYP]U_h%K7lem/^T5uY*I9)k)K9@-(!&"d(Uj9+d6LB[LiCt-4a!HP^Z0TZh"URA>d9hUp@=^9M$ec%3qMQ3[8d5-2W,9a]2U\llmnJ6NB[2_e]M(ED.ecUBn>'G^9M3e\qAId'8t3XL5i'2@+&:=(AO6pd?REBK@XHJ2.VKAUGa^Hc#&PG&6)+kI,KK\?ajSSc`mAWCEFa",4XWU?8"nChB4r1TJQ=SthZiq5dr6IUPr?/])f.D66a@>J,dlbI@tkM^X1J^d_\JI2bP_Pbepmm%a1X01ol*hlT9Ik$(_'NZRQ02S1>jrmJAhOQ:u"+L[8&H~>endstream +endobj +11 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1465 +>> +stream +GauHKgN'&Y&:O:SoV4=@&4#$XDr/WRj)!8C8rnF8bQs2Y&RiI-rI%EOOtGE\(+4u4/GGTiq>?OX6*-oX]>f+J-PN.ORS0d@(mlUus0Ah2hP%M0hRQBagICsoA+NR;/"O9=X(1oM*='`qF*t5<:X0,L6hV`%i"d@KF(sp+Cp=>W#-6F(#44O_@/5$)_VdYR4#(^^&#"c*L9:GGc)sl#jh-0)<,g#D2#r6C\ul$%S+Wq"n;m9Z8jZbi_:`8ISh"Z^k(n'/X.ENiQ)\sc9EOZIJj6ji8P`:R"^qri9C`jIS7Njh;&[D,Mp4cQ*9PVA>uTt(2N'`pg1b&>9@oe+/>#msb`sK;9YV`lq6rL^ip[#WGbtVabW)e3VOf^&-n]Vdk+g]0PfoK.Z0i7tT!cif0p14FG'Y;ku.^e2"%5KFHkA?R#1J0u?+SGVSGHl8j(HXj^k#1IXrCYc=F%8R,#Kf2mTWOSC^^3cZAX\]BK[2''d=tCZd@g^p8rF^_@T?5,6(%>q"SeD,X9br24)\4b-&\8GsUInr(.G13TT=.Y44WnU;+8:C.Um-RG.RoDl>XA(qRaI+9d09lq:f4.5!E%36JA.Q5A]m'UQL;Q*'go5>rE$\8fV9DR'`.^:NWZY&m_i+oS]7e/<)#"([OPoqR6RfU%H2tA@Gln-^dLg&K9?C&jd2,[8+4\GD'+RfipE"rPZ-?,>)D_HHA*=J+0N04lWU--I7N/iuf`?4OGKIDIL"[\'clLK>SJ'N;&u,4\A>M&BF26hcZ\;B$5XT%4CT3esHr>:"lbG1ppFtM5(UaQfoUpkQUg-DlXpH!L<>#$Eg$8R[R57Ck>2d)&p\;GR/14begdIFm3+Ab$a`!"$H?6,lZ5_Y@;f4%A/(CTtD?EcbL3&a^Ar6o,KB~>endstream +endobj +xref +0 12 +0000000000 65535 f +0000000061 00000 n +0000000112 00000 n +0000000219 00000 n +0000000331 00000 n +0000000446 00000 n +0000000650 00000 n +0000000854 00000 n +0000000922 00000 n +0000001214 00000 n +0000001279 00000 n +0000003320 00000 n +trailer +<< +/ID +[<478ddb229fc9bd4f3be95b83bd28842d><478ddb229fc9bd4f3be95b83bd28842d>] +% ReportLab generated PDF document -- digest (opensource) + +/Info 8 0 R +/Root 7 0 R +/Size 12 +>> +startxref +4877 +%%EOF diff --git a/lab_rag/dokumen/etika_keamanan_ai.pdf b/lab_rag/dokumen/etika_keamanan_ai.pdf new file mode 100644 index 0000000..2779b4b --- /dev/null +++ b/lab_rag/dokumen/etika_keamanan_ai.pdf @@ -0,0 +1,93 @@ +%PDF-1.4 +%東京 ReportLab Generated PDF document (opensource) +1 0 obj +<< +/F1 2 0 R /F2 3 0 R +>> +endobj +2 0 obj +<< +/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font +>> +endobj +3 0 obj +<< +/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font +>> +endobj +4 0 obj +<< +/Contents 9 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 8 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +5 0 obj +<< +/Contents 10 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 8 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +6 0 obj +<< +/PageMode /UseNone /Pages 8 0 R /Type /Catalog +>> +endobj +7 0 obj +<< +/Author (\(anonymous\)) /CreationDate (D:20261102015146+00'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20261102015146+00'00') /Producer (ReportLab PDF Library - \(opensource\)) + /Subject (\(unspecified\)) /Title (Etika dan Keamanan Kecerdasan Buatan) /Trapped /False +>> +endobj +8 0 obj +<< +/Count 2 /Kids [ 4 0 R 5 0 R ] /Type /Pages +>> +endobj +9 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2190 +>> +stream +GatU3gN)%,&:O:Si6fg%X@V.hSL.([1`[rE56)=)&HW9E,`mu^ofW\5V!Q0uXc18c8-!usHhN&Y:%4"qs'T9PW/C5eoJ\$05P];RlB^1d8:bQ"eWh)-1Rp2o?O;6o5@&e?,dJ'.s]#^SoXN7>$Ii$e1BbRESoAFcibUAoGbC(:=nYa'ff4+Rp5&&/&ZX#o%[_$FY7I-<17*mS'`>^DHXWntKVk,MYLi9fC6hNnPN'!s*A3[?Ti4fmS1+RV;P(Ed6%4N37:j$D@U.#,2j!CMB;s7)Cig0;niM?:)XUS5,nS.T:.He_ZB1Nmn/Po?l!H7aR\ZZj2tD]gJf)(E?i[BXOVZuD!aQ$C*9Gd\HA`G>T8H9?5?P?Xsc7mQS.+9K;=-[!tO>1DVP+R#$XrC"YGP4aDCt=p/Z7-46ZNgI4k8XLu$YQ)u33bGUmg6;sU/GR6Z[7T#s@\a\QKd439\O[+(h4SFGnTE&=Q,!<@]j>;IIH_>XJso`!QoZ+nJVXBDi>Rm>UOktj!fFD4j;HqF;SNf%m8%A*WfmIr9uijK?<4!-$E;s??f2n2"Ku(@0HbjT!MpFJQKJP&-^!+X.coPo1+JZk]OF>I?M.L7G(/LH81i*PC\Jo;E`)?r[4FBLgF14N`L4h+NS"H$2\hU9OE$nG5rhEr4::d2XjcrfQ4:bjoUXE\L)D1cY$c>1X)toZ#UN_I,4\UUnXpcb;an[)c;iF,-!_2<#c5B,7XtqaIc(JY66#a)d?0S/Gq,7=W'UgMsofET6JTT6RHTc_jufNPp@qcUp?#F#5t8o:kF@pA#L)WfJ#11j>SNuYIYRMkSio-aPDbNE5k?Vmj"9p7[AZq,>"&j.2kL;CfPUtCMAN6ZUead:fCR:0kl"9U^t,/-o$=rb*Q7Ggo0dE*HecmfH;q-lq'jG,dithChU=2^'E!sq2B;k=c\'N^:J]i\GO-07-YJ>&bt\:LG6WSi`cLN&WeZ2O@hi,TlTe!$AHb8g1#'B8(p;B)K-!:(dEH71=TuYd*Bl=NM!D$R"JJCC\]+U*^+J7b%R>`*-Lb\.bEjbcr>Tg(sO:Sno/(KR-tY!&MO6Sd#'>KFYjVB%jJ6&_&sTf`-r-1L1B4S0u]>g$EEQgP.T*i^b^39Duj&n]`)T0/8+RA4oL+()CO*LjGR`:/E[Ca*A:PIf_q:07f+;g$^2ZN_/,AFq3eTu?981mF3uf:=Vp):,ap%Nj;cR]_EKJrMQ?Yi5+.rdqXZ--\.l\].c%VTOdOH!dqO,#nm/cnQDR'2P3sr(,.G08k\aX=)g"?PN2D$8$=<=^7u^H`@TW]$[?D&d*dpinC0'aB?(C)C)>7aNY_-F(ZP878!6R0*]at3PEcBDQFhpVr5F*:`W+`#0XL~>endstream +endobj +10 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 536 +>> +stream +GasIc997OU&AIm?I)dih+`=ocjTYc=^]BSX?7(Y'>X)\,>DRdTfI=H!9"U?7/'<+Nf8Mu>8!Nm]JIa?hHkm8tZp,`-eK4*ZHtl`t;lbkI[SA'Wp(.d)M*$aD40LVhYBBIOS.82D,Mc\1b0EfiCo<2B!rCXY,lSK=E2>'T_WqhNsWNg,9`mR0*];!M$`LS;i:L*&lF)qAqlK-ck9b&RsESBsNe"`m+*T46g8rWuqQ20,(o>E=X@A_0(h/%sYT/gCI2Uh/G;;pQ2'.`&b'^X=BF.qsq?deZg9BeicO'[*t/0,VQE0HD/^8Z>qV(mZsdr091b7.61+ju_t[^A(=A^Hs_=W.YD58,cB'=k2&d\8`,Ok1i!0%%1bHZ;QEh=\GqcVNlSf]TM,+o^lo=09^KmoC0"-t@.b=;2@(E~>endstream +endobj +xref +0 11 +0000000000 65535 f +0000000061 00000 n +0000000102 00000 n +0000000209 00000 n +0000000321 00000 n +0000000524 00000 n +0000000728 00000 n +0000000796 00000 n +0000001099 00000 n +0000001164 00000 n +0000003445 00000 n +trailer +<< +/ID +[<7636af93ea22ee58f59714add6924af0><7636af93ea22ee58f59714add6924af0>] +% ReportLab generated PDF document -- digest (opensource) + +/Info 7 0 R +/Root 6 0 R +/Size 11 +>> +startxref +4072 +%%EOF diff --git a/lab_rag/dokumen/machine_learning_dasar.pdf b/lab_rag/dokumen/machine_learning_dasar.pdf new file mode 100644 index 0000000..1eb0d39 --- /dev/null +++ b/lab_rag/dokumen/machine_learning_dasar.pdf @@ -0,0 +1,93 @@ +%PDF-1.4 +%東京 ReportLab Generated PDF document (opensource) +1 0 obj +<< +/F1 2 0 R /F2 3 0 R +>> +endobj +2 0 obj +<< +/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font +>> +endobj +3 0 obj +<< +/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font +>> +endobj +4 0 obj +<< +/Contents 9 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 8 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +5 0 obj +<< +/Contents 10 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 8 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +6 0 obj +<< +/PageMode /UseNone /Pages 8 0 R /Type /Catalog +>> +endobj +7 0 obj +<< +/Author (\(anonymous\)) /CreationDate (D:20261102015146+00'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20261102015146+00'00') /Producer (ReportLab PDF Library - \(opensource\)) + /Subject (\(unspecified\)) /Title (Dasar-Dasar Machine Learning) /Trapped /False +>> +endobj +8 0 obj +<< +/Count 2 /Kids [ 4 0 R 5 0 R ] /Type /Pages +>> +endobj +9 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2005 +>> +stream +GatU3bBDVu&Dd46Y]O]>&LgV=A^f-lVg26]Pch8MP-#]EdfbGn);LXj1\B?;5Mof91WJ:Rf\9W&q#O]:QlgVt>CC%3X=jLcn=)A7;`9O\hL*&)@g<-H/'uBApA1=@Cs8P%@/cZq"T^&U/A,XNT0p8Kg#[QeEBUU/p5.[FAM2V*_0%C%j:,bbad5YGN$1;-"n?ampTZe(OMlX\%_6joFG/mU7fT#+%I7XQiN[`oITPMHD:8(5b.V&$=0/'1[qMkn]4b%8OlrkqqdEh:1"PAiY`-7<7m`WGqF(n0XKk%iCo`bGo]h68ZsmG(t22F?@,2)%YHR4)L-'I17V%TdX)u"R$hVG4e9]QB*1ckfimBcFRE7ofN*%;1G&2.64C7n3`Ne0I!,<:?5o\t,)r-BSo1CmjpG[$#ph)nj[\CSo,9'/&/\-PA(;(SFg9Rj_Y1Aqf*60=K$I2VT'V[4?PI#dEDu>gcHrk:OWlsodr!cjaU!=srA^VP\[<+1Cq?RFd6AD"=r-og6^-afeVc6VfU;#,W2UPPDkRk\"K/9q=t88_/PnU*Q!G?5^bFMle'Y$hEJNr[Su%17pS^2c$Hd.b#n]E8nZmLp(5KELdKQGEr\e&.$NKH2VX*N)s!Q3;?+i_1rrRqMW(p*K3r\a,lC0*l'LP@O>]A1u#mm+MnIh%,3rmbK?u.)X'F,GlS=j"VH)YMbYUV3X6R96a>/kS?QQ/fBanYKRGrQrl:lhP4q!u>KK?tc?6$.FI30KH>22kol:853D4W`EIA5QX-.eQM/gU>WU-OEl8.=V1@(U,J)5AR2*8+h)nqcaMe&A3l8>t5V:,5Z%KV3K`ebQe=LuhG3'9F:pOI96:9<_Xm0#W)UrXp'K6AZd:OsTT03Cqh>*=[-l!$2uFdtlO0'"lR/[]%?U<]bgatfKh\HNF,P]`m(P4Wl;13(4;a%1,JoBt#1_.jZr4\T)h(\F_rYUo-Xh1:;dtjNfqtoJiH+j(PrQX*ZmeV*PI>dc4Pg6N,_=DEcYX_NYb[.E`A*MH%SY:J>F9(,L?NSIi#2Vr2-]I;TBUJfs0VXrq82[_]r;%>9<-fIY1K8Q@]dSBU0JEVY(Du@C"OcA]G1uriJlI'(mbhi*FU+G&f68l?V)+$GGF1Buk:c`r>^4ZK?VJ<5HiNR6KS]S?Rm>Q6!N["4C'EYVoC:,dEW=nRNPfM.o:Z/bendstream +endobj +10 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 909 +>> +stream +Gat=hc#28i&;9M$MEN;?X'5KuO%#NXl9h$*R*3XJ.7OrL;IYNrI>=%=a),;gJH/ms`VjsmB:70N:E"_l2:7bL52E*#:+=pp3`"n&D?S7\P>#(7RqIY^#fU0SdVa`Y8%cQQlK!Mru2@8gX[g9gQIel*lmP?k?<66^2C8CBbDNekYSgaIIGX(\f12#'obWTrPt)q/_B5Ud-U/b#*e=K`.BKlLb!&-mV4*'FLpU8PO>7,:@ID#NM9V-NH@0BYGksN[DXtgP42ct'#&s<(&qkJeV#adJ#Wb%c5VJ1V0$$X2@44G3s1HK&D8kNE4YV)bEcEVk+4ZU?QkD\bs2m;=ZRkRQs(pu[)ngB.-4K2rrsTf;dlBZ3p5pI5F:u\7@DVo2eB^YXAiu156A2D%OqmmNsAsD/p%>88?gRA-g)Vu^&l+kO"&\sL+`s@S1hRnp1udGJPSDV7;Z^7Kjl(f$^qdm$VXXj2!c]C:UdpcekkM)7$`QKfEb^1X`^p4lef\@Z@D%U$TjH^5Rnfh?;[VnNdsqY\7#V:h8+]>$WbhPGA%9H](&mITdUn,iG>8&]!mAV3padZ@7"]qgB@/h\qU"]k[<9.;"uXYNeE?hSGV0,H0AF'9aDaKqT?Y%P*dNiAD]E(i`d+Z_pe7&Ku+N0O4P)0#a&P"R%j6j\WC&<4q'`N".#Ne+Z?GD0TD8_QP_fSp;m36,8Sb]3utS\$rZm.pm.!9s$>eJbP1(clg$E_2X._iieH4=N^JrG3f=IWA!Ga'`i_F4g7VT$kr6%38dbjt;(%@endstream +endobj +xref +0 11 +0000000000 65535 f +0000000061 00000 n +0000000102 00000 n +0000000209 00000 n +0000000321 00000 n +0000000524 00000 n +0000000728 00000 n +0000000796 00000 n +0000001091 00000 n +0000001156 00000 n +0000003252 00000 n +trailer +<< +/ID +[] +% ReportLab generated PDF document -- digest (opensource) + +/Info 7 0 R +/Root 6 0 R +/Size 11 +>> +startxref +4252 +%%EOF diff --git a/lab_rag/dokumen/pengantar_rag.pdf b/lab_rag/dokumen/pengantar_rag.pdf new file mode 100644 index 0000000..49f2d7d --- /dev/null +++ b/lab_rag/dokumen/pengantar_rag.pdf @@ -0,0 +1,93 @@ +%PDF-1.4 +%東京 ReportLab Generated PDF document (opensource) +1 0 obj +<< +/F1 2 0 R /F2 3 0 R +>> +endobj +2 0 obj +<< +/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font +>> +endobj +3 0 obj +<< +/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font +>> +endobj +4 0 obj +<< +/Contents 9 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 8 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +5 0 obj +<< +/Contents 10 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 8 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +6 0 obj +<< +/PageMode /UseNone /Pages 8 0 R /Type /Catalog +>> +endobj +7 0 obj +<< +/Author (\(anonymous\)) /CreationDate (D:20261102015146+00'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20261102015146+00'00') /Producer (ReportLab PDF Library - \(opensource\)) + /Subject (\(unspecified\)) /Title (Pengantar Retrieval-Augmented Generation \(RAG\)) /Trapped /False +>> +endobj +8 0 obj +<< +/Count 2 /Kids [ 4 0 R 5 0 R ] /Type /Pages +>> +endobj +9 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2164 +>> +stream +GatU4bAs(C']&X:ma=\K$m6_89.,q!At7?r[Utk#,MK(*1e^7aQ+rr4Rtm(IaH=Z+ACQ$7kM2C:OH6$L]l"4PG8pD=@mE=NRl^rmhL[YXl,2ZM^U'TF\QmQ4RX=AnjVeaknD/XecQF/8l6'1oBQHt=[rcV_#0qY7c_5u"E7D^;E,b5S?*f1HJOf'm1lW-:@(&#jPaQ(s*QR-elRW':TDsYJaOtlBe0GZhM]E+&X%$]\2=sQ*PTZ'b,.9PWi+XM1U4,^isVXd#s-$/heOVp$d;(9)cWKWW;'nWHk.@o#G$0SRU3MP&'b?1Q,;-"n%XJSH$lk^.bBEfCe],*\#$o^ktc3`l4P2S'SOtg<+9*SKoA0t]@PZF"sR*DFEOXP:]UX/M/W[Ybo#/BeaH_h)A&;-c-oKs^PoMKF9>a?75rA?ua,ASaPG3@8mh?-RY]-EUr[fug]TUab?Bjg>p'XD+mQ"D*X(jM+VYLUh2O7r0GZ;*8jK)T2=rl>aQ>*p*:#.L:mk+2)Qf;Q(/jAD,QuQlOnfX:Xae$@$Oso@3)n0OtVt:'K?Q,*#4@tc4B9XW6E3!#.`?b^A$JaA+XVrj5P0q86F_,S)AV\?C<22)@e8"MI*!bkE#\q/j@9\XVGgs"`U31m`LfI1f3LEt_.KSm7EeW7`md,lp8k*(uMLGT:.Vh[2P9#+;.>t2LWuINKoZCl%(T3S>gnPC.n1NIuAV%Lrp9$SjDgqM^3n[a(>*"f26"@b?7`TM^(hmj72`_KN\8\)Z.InP<6if]"+.^.c+p5PdcoaOBEI>@LRHEg(00[8j5hp7%Fa.ujWmP;5ICRs8i(l@FD6Iib>k^k;:"ebpVaQ9HF"ibrHH0K#8:C#Oc$ki4H$K.Rq*%VIm?TPYMR;C(6\/ckW/,:nF6>hh"*C<,?aIRMNDENS6t#n3q%=+-TAN7/Y$AIh.RaB5gO@4R#>AcnRpkI\RNuLLD;;;CXpsg5DH,38$5:tK/B0*\7KXZ`6eKQP/8R^]6i3$V/jXF1L,lMNi2%2LLV:G\k\iEa&M"&<,ZoUH+YD+"RMLTo\]$i$1N8_(X]SFE;5]iS:L+5B*kg`k1MTf`)$hJe23mudhpXiNCO)?'Ek@OI^';2lBjbiC'jK=bD]YF]n0.B$_$Cs'KhMr'ha_.[TH*O7r4sFT32Gs\[\\j;EOlF.p$mSj;2"skAf22K_JQ.<8lK]H_k_$H$XG]R)p&DAfOJH7h3G)ER7jC?\(\Pp%<6$J6Nn_YAMKF.8<(-S>fKmW%'R]V#B!JAp0%ZN$B#652X(_&QJ.*E6G';M?kVK2h+tt&S,gqg"T0l-=/OZrel_iX!\5gr0oFS!^-##d[U4'9G7^E2GPcNG$b)D5[u#fDR?n**A"'I[$bdI(qa*B?Wf>#H!s?9+-O.4'j"Y+l]jfHkAS^%)LT+^U".1b>VAI9:'E-g;Ea/>L$=9e$M3_dg>^=B^RIHjm!QQmp0^QS(I90dN\U+`R1Ul*J]%a9GucVnCYTZCeopi+mu0Ti>m[:IVLbek1O`D:,..PIG7PJ@`_FLn+a6WgOtf=St(^#P7$\bl3'%[o*qq&%lfEl=TL`4X00Wr"fol!l#pns,X(^4HQW],o+GoEB6l\p!7NV_R(l)j79:$_U.38GCSaDIW2hc?[_Emo*IqZZZ!.g^8p^>WM)'@)5r00UEuL?&)=eO%I"_aAYGc2H#Bs!Z1g0)~>endstream +endobj +10 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1431 +>> +stream +GatU2gN):C&:N^lqU%kH77&+>:V2Y]P&*$V#*M)-BFNp`7`n9-bC?/5,9_G%Y&]E*OlghucT0fK6m4aVs1ca6/iWFokD5i=D/Lbj##j7R6(^'1In*AF1.c.CSHk(lEe,6u#lTG2O,eQS^N]6h-OtO7-0c_jNng82oERd)^dU'f6Se#\eB7_TRp4VE.*#ZSF#l@N7):'N/Dl*LXg#2g'kIhUB)s@L4@nK-K&WKqU\H]s[4*(E]2O_f[^7Vkd0!\(Ki.OpCcmW.kq&7;-a0Sf1qBo&6!g[3W+:7uG5hp#n+aL8"g]md-4rE@?@BX(h2eXmb6;cL)6GVI:#]P9T-\s!J*ElKVrM2MN"rOuO.odXU29.&qWUQk[2R,.s3a]`E2D_iVYc]tqYD)7io3OM`l0<7VoZNG2@AO`m*8d3Rs_9l0BBLr)m5iLWGId_.QAq*0U(VX:!=)einXaMKu]YdoXEQ)E7,[)e0%:EGrr:mfuuLE8mho/HI+[R6ONXd.C/Un`d$4)#&d%Za%g-G<]0f_B0<\')6O)FG_0Ol;U$t^0d=MZV;**6*V!/Q8io3"MV7Q;-V!8&qodH"M@V?@1natQ:;M6V`U4h)?\%:\oQLB)L/RP1X@ug-"m[B)49lQ1*C1qg)X:`=cii.3.XOWX2ct\?jWAm.=SZuG"WT]"#*l29g#==2AR51`4o[#=Llm-#c`;CB@koM5m0*3RaV[`!nD-'raq,5h@G>+@ipXREQ`X6V)Z4CPDd-2bN5H_`Kn1e.r2OarrV16u1q.6i;2-_?43.+JLVPHu1UEPV]3*Oj-+8%UuI*":sD,kKhW8WoQEOgg4D+CA!oas[FHpBJ%E\`9mJdE$V;k4B(JfFZ:2P16H'eZ\sp!ng_ef*i=6+$.KX'j$5-bR_*7\S+\R_20kel(IrKbZ(XKq>'QB$s:DF;1:?$`1GH/8jr5NWWI5r:7@GmY1#@Q&gj\Sj$k14i;;C$2Em;fV8A\i`j:(&uaaa.7+5P.5m0;RUE`><^i7&@B,"S8\!h"d)Y,nOiuT'p3jfOlLL4C%NJkno^#~>endstream +endobj +xref +0 11 +0000000000 65535 f +0000000061 00000 n +0000000102 00000 n +0000000209 00000 n +0000000321 00000 n +0000000524 00000 n +0000000728 00000 n +0000000796 00000 n +0000001111 00000 n +0000001176 00000 n +0000003431 00000 n +trailer +<< +/ID +[<94e0708a6e608b44ad056752ec8119b5><94e0708a6e608b44ad056752ec8119b5>] +% ReportLab generated PDF document -- digest (opensource) + +/Info 7 0 R +/Root 6 0 R +/Size 11 +>> +startxref +4954 +%%EOF diff --git a/lab_rag/lab1_chunking.py b/lab_rag/lab1_chunking.py new file mode 100644 index 0000000..5adcc7c --- /dev/null +++ b/lab_rag/lab1_chunking.py @@ -0,0 +1,300 @@ +"""Lab 1 - Eksperimen chunking (15 menit). + +1. Baca satu PDF dengan baca_pdf() dan cetak 500 karakter pertama. +2. Potong dengan potong() memakai tiga ukuran (500, 1000, 1500) dan overlap 10-20%. +3. Lihat 3 chunk acak tiap ukuran: terpotong di tengah kalimat atau tabel? + +Versi ini dijalankan untuk ketiga PDF AI. Satu laporan PDF dibuat per dokumen: + Lab1_Eksperimen_Chunking_1.pdf, _2.pdf, _3.pdf +Jalankan semua : python lab1_chunking.py +Jalankan satu : python lab1_chunking.py 2_Machine_Learning_dan_Deep_Learning.pdf +""" +import os +import random +import re +import sys + +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +from laporan_utils import Laporan +from rag_utils import FOLDER_DOKUMEN, baca_pdf, norm, potong, potong_dengan_posisi + +BASE = os.path.dirname(os.path.abspath(__file__)) + +# Ketiga PDF yang dipakai. Letakkan di FOLDER_DOKUMEN, di folder skrip ini, atau di folder kerja. +DAFTAR_PDF = [ + "1_Pengenalan_Kecerdasan_Buatan.pdf", + "2_Machine_Learning_dan_Deep_Learning.pdf", + "3_Etika_Risiko_dan_Masa_Depan_AI.pdf", +] + +# PDF ini tidak memakai penanda "Tabel N." / "Sumber:", jadi wilayah tabel ditentukan lewat +# teks baris judul kolom (awal) dan teks akhir baris terakhir tabel (akhir). +PENANDA_TABEL = { + "1_Pengenalan_Kecerdasan_Buatan.pdf": [ + ("Periode Peristiwa Penting", "secara luas."), + ("Sektor Contoh Penerapan", "pembuatan musik dan gambar."), + ], + "2_Machine_Learning_dan_Deep_Learning.pdf": [ + ("Paradigma Penjelasan Contoh", "hadiah dan hukuman."), + ("Arsitektur Kegunaan Utama", "konten sintetis."), + ], + "3_Etika_Risiko_dan_Masa_Depan_AI.pdf": [ + ("Isu Penjelasan", "pelatihan."), + ], +} + +UKURAN = [500, 1000, 1500] +OVERLAP = [0.10, 0.15, 0.20] +OVERLAP_UTAMA = 0.15 +SEED = 42 + + +# --------------------------------------------------------------------------- utilitas + +def cari_pdf(nama): + """Cari file PDF di FOLDER_DOKUMEN, folder skrip, lalu folder kerja.""" + kandidat = [os.path.join(d, nama) for d in (FOLDER_DOKUMEN, BASE, os.getcwd())] + for k in kandidat: + if os.path.isfile(k): + return k + raise FileNotFoundError(f"{nama} tidak ditemukan. Sudah dicari di:\n " + "\n ".join(kandidat)) + + +def bersihkan_footer(teks): + """Buang baris nomor halaman ('Halaman 1') yang ikut terbaca di tengah isi. + Dilakukan sebelum pemotongan, sehingga semua posisi karakter konsisten.""" + baru, n = re.subn(r"^[ \t]*Halaman \d+[ \t]*\n?", "", teks, flags=re.MULTILINE) + return baru, n + + +def wilayah_tabel(teks, penanda): + """Rentang karakter tiap tabel: dari teks judul kolom sampai akhir baris terakhir tabel. + Penanda yang tidak ditemukan dilaporkan, bukan diam-diam dilewati.""" + hasil = [] + for awal, akhir in penanda: + a = teks.find(awal) + if a < 0: + print(f" [PERINGATAN] awal tabel tidak ditemukan: {awal!r}") + continue + z = teks.find(akhir, a) + if z < 0: + print(f" [PERINGATAN] akhir tabel tidak ditemukan: {akhir!r}") + continue + hasil.append((a, z + len(akhir))) + return hasil + + +def batas_bersih(teks, pos): + """True bila posisi `pos` jatuh di batas satuan teks yang wajar (bukan di tengah kalimat). + + Newline TIDAK otomatis dianggap batas, karena PDF memecah baris di tengah kalimat. + Batas bersih bila: awal/akhir dokumen; ATAU tidak memotong kata dan teks sebelumnya + berakhir . ! ? : ; ATAU bagian berikutnya diawali butir daftar ('- ') / judul bernomor + ('3. ') sehingga teks sebelumnya adalah butir atau judul yang sudah selesai.""" + if pos <= 0 or pos >= len(teks): + return True + kiri, kanan = teks[:pos], teks[pos:] + if kiri[-1] not in " \n" and kanan[0] not in " \n": + return False # memotong di tengah kata + kiri_s, kanan_s = kiri.rstrip(), kanan.lstrip() + if not kiri_s or not kanan_s: + return True + kata_akhir = kiri_s.split()[-1] + if re.fullmatch(r"\d+\.", kata_akhir): + return False # nomor judul ("3.") yang terpisah dari judulnya + if kiri_s[-1] in ".!?:": + return True + return bool(re.match(r"(-\s|\d+\.\s)", kanan_s)) + + +def awal_di_tengah_kalimat(teks, mulai): + return not batas_bersih(teks, mulai) + + +def akhir_di_tengah_kalimat(teks, akhir): + return not batas_bersih(teks, akhir) + + +def memotong_tabel(wil, mulai, akhir): + """True bila chunk beririsan dengan tabel tetapi tidak memuat seluruh tabel.""" + for a, b in wil: + beririsan = mulai < b and akhir > a + utuh = mulai <= a and akhir >= b + if beririsan and not utuh: + return True + return False + + +def pct(x, n): + return f"{x}/{n} ({x / n:.0%})" if n else "0/0" + + +# --------------------------------------------------------------------------- narasi dari data + +def catatan_kualitas(k, n_footer): + """Penilaian kualitas teks yang dihitung dari angka, bukan ditulis tetap.""" + masalah = [] + if k["Karakter rusak (U+FFFD)"]: + masalah.append(f"{k['Karakter rusak (U+FFFD)']} karakter rusak (U+FFFD)") + if k["Sisa kode glyph (cid:)"]: + masalah.append(f"{k['Sisa kode glyph (cid:)']} kode glyph '(cid:N)' (simbol gagal diterjemahkan)") + if n_footer: + masalah.append(f"{n_footer} baris nomor halaman 'Halaman N' yang menyelip di tengah isi " + "(sudah dibuang sebelum pemotongan)") + if not masalah: + return "Teks terbaca bersih: tidak ada karakter rusak, kode glyph, atau sisa footer." + return "Temuan kualitas teks: " + "; ".join(masalah) + "." + + +def buat_kesimpulan(statistik_angka, jumlah_tabel): + """Kesimpulan yang seluruh klaimnya dihitung dari statistik, jadi benar untuk PDF apa pun.""" + rincian = "; ".join( + f"ukuran {u}: awal di tengah kalimat {pct(a, n)}, akhir di tengah kalimat {pct(z, n)}, " + f"memotong tabel {pct(t, n)}" for u, n, a, z, t in statistik_angka) + kal = [f"Pemotongan per karakter tidak mengenal batas kalimat maupun tabel. Hasil seluruh chunk " + f"(overlap {int(OVERLAP_UTAMA * 100)}%) - {rincian}."] + + pz = [z / n for _, n, _, z, _ in statistik_angka if n] + pa = [a / n for _, n, a, _, _ in statistik_angka if n] + if pz: + if min(pz) > 0.5: + kal.append("Pada setiap ukuran, mayoritas chunk berakhir di tengah kalimat.") + elif max(pz) < 0.5: + kal.append("Pada setiap ukuran, kurang dari separuh chunk berakhir di tengah kalimat.") + else: + kal.append("Proporsi chunk yang berakhir di tengah kalimat berbeda antar ukuran " + f"({min(pz):.0%} sampai {max(pz):.0%}).") + kal.append(f"Chunk yang dimulai di tengah kalimat berkisar {min(pa):.0%} sampai {max(pa):.0%}; " + "chunk pertama selalu dimulai bersih.") + if max(pz) - min(pz) <= 0.15: + kal.append("Persentase chunk yang terpotong tidak banyak berubah saat ukuran diperbesar; " + "yang berubah adalah jumlah chunk dan banyaknya topik per chunk.") + kecil = [u for u, n, *_ in statistik_angka if n < 10] + if kecil: + kal.append(f"Catatan: dokumen ini pendek sehingga ukuran {', '.join(map(str, kecil))} hanya menghasilkan " + "kurang dari 10 chunk; persentasenya mudah bergeser oleh satu chunk saja.") + + if jumlah_tabel == 0: + kal.append("Tidak ada tabel yang terdeteksi pada dokumen ini.") + else: + kena = [str(u) for u, _, _, _, t in statistik_angka if t > 0] + if len(kena) == len(statistik_angka): + kal.append(f"Dari {jumlah_tabel} tabel, minimal satu terpotong oleh sedikitnya satu chunk pada " + "setiap ukuran; baris tabel yang terpisah dari judul kolomnya sulit dipahami.") + elif kena: + kal.append(f"Dari {jumlah_tabel} tabel, pemotongan tabel terjadi pada ukuran {', '.join(kena)}.") + else: + kal.append(f"Dari {jumlah_tabel} tabel, tidak ada yang terpotong pada pengaturan ini.") + kal.append("Perbaikan yang layak dicoba: pemotongan berbasis kalimat/paragraf dan memperlakukan " + "tabel sebagai satu chunk utuh.") + return " ".join(kal) + + +# --------------------------------------------------------------------------- satu dokumen + +def jalankan(nama_pdf, nomor): + pdf = cari_pdf(nama_pdf) + print("\n" + "#" * 70 + f"\n# {nama_pdf}\n" + "#" * 70) + + # ---- Langkah 1 + mentah = baca_pdf(pdf) + teks, n_footer = bersihkan_footer(mentah) + if not teks.strip(): + raise ValueError(f"{nama_pdf}: tidak ada teks yang terbaca (mungkin PDF hasil scan).") + n_huruf = sum(c.isalpha() for c in teks) + kualitas = { + "File": os.path.basename(pdf), + "Total karakter": len(teks), + "Karakter rusak (U+FFFD)": teks.count("\ufffd"), + "Sisa kode glyph (cid:)": teks.count("(cid:"), + "Persentase huruf": f"{n_huruf / len(teks):.0%}", + } + print("=== Langkah 1: 500 karakter pertama ===") + print(teks[:500]) + print(kualitas) + + # ---- Langkah 2 + print("\n=== Langkah 2: jumlah chunk ===") + tabel_jumlah = [["Ukuran (karakter)"] + [f"overlap {int(o * 100)}%" for o in OVERLAP]] + for u in UKURAN: + baris = [u] + for o in OVERLAP: + n = len(potong(teks, u, o)) + baris.append(n) + print(f"ukuran={u:5d} overlap={o:.0%} -> {n} chunk") + tabel_jumlah.append(baris) + + # ---- Langkah 3 + wil = wilayah_tabel(teks, PENANDA_TABEL.get(nama_pdf, [])) + print(f"\nTabel terdeteksi: {len(wil)} -> {wil}") + rnd = random.Random(SEED) + cuplikan = {} + statistik = [["Ukuran", "Jumlah chunk", "Awal di tengah kalimat", + "Akhir di tengah kalimat", "Memotong tabel"]] + statistik_angka = [] + for u in UKURAN: + pot = potong_dengan_posisi(teks, u, OVERLAP_UTAMA) + n = len(pot) + a = sum(awal_di_tengah_kalimat(teks, m) for m, _, _ in pot) + z = sum(akhir_di_tengah_kalimat(teks, e) for _, e, _ in pot) + t = sum(memotong_tabel(wil, m, e) for m, e, _ in pot) + statistik.append([u, n, pct(a, n), pct(z, n), pct(t, n)]) + statistik_angka.append((u, n, a, z, t)) + pilih = sorted(rnd.sample(range(n), min(3, n))) + cuplikan[u] = [(i + 1, pot[i][0], pot[i][1], pot[i][2], + awal_di_tengah_kalimat(teks, pot[i][0]), + akhir_di_tengah_kalimat(teks, pot[i][1]), + memotong_tabel(wil, pot[i][0], pot[i][1])) for i in pilih] + print(f"\n=== Langkah 3: ukuran {u} ({len(pilih)} chunk acak) ===") + for no, m, e, isi, aw, ak, tb in cuplikan[u]: + print(f"--- chunk #{no} [{m}:{e}] awal_tengah={aw} akhir_tengah={ak} potong_tabel={tb}") + print(isi) + + catatan = catatan_kualitas(kualitas, n_footer) + kesimpulan = buat_kesimpulan(statistik_angka, len(wil)) + print("\nKualitas:", catatan) + print("Kesimpulan:", kesimpulan) + + # ---- Laporan PDF + keluar = os.path.join(BASE, f"Lab1_Eksperimen_Chunking_{nomor}.pdf") + L = Laporan(keluar, f"Lab 1 - Eksperimen Chunking ({nomor}/{len(DAFTAR_PDF)})", + f"{os.path.basename(pdf)} | Python (pdfplumber + fungsi potong)") + L.h1("Langkah 1. Membaca PDF dan memeriksa teks") + L.p(f"File yang dibaca: {os.path.basename(pdf)}. Berikut 500 karakter pertama hasil baca_pdf():") + L.kode(teks[:500]) + L.spasi() + L.tabel([["Pemeriksaan", "Hasil"]] + [[k, v] for k, v in kualitas.items()], [6 * 28.35, 8 * 28.35]) + L.p(catatan) + L.h1("Langkah 2. Jumlah chunk tiap pengaturan") + L.p("Fungsi potong(teks, ukuran, overlap) memakai jendela geser per karakter; langkah = ukuran x (1 - overlap).") + L.tabel(tabel_jumlah) + L.cap("Tabel 1. Jumlah chunk untuk 3 ukuran x 3 overlap. Makin besar ukuran, makin sedikit chunk; " + "makin besar overlap, makin banyak chunk.") + L.h1(f"Langkah 3. Tiga chunk acak per ukuran (overlap {int(OVERLAP_UTAMA * 100)}%, seed {SEED})") + L.tabel(statistik) + L.cap("Tabel 2. Statistik seluruh chunk pada tiap ukuran (bukan hanya yang dicuplik).") + for u in UKURAN: + L.h2(f"Ukuran {u} karakter") + for no, m, e, isi, aw, ak, tb in cuplikan[u]: + L.p(f"Chunk #{no} (karakter {m}-{e}) | awal di tengah kalimat: {'ya' if aw else 'tidak'} | " + f"akhir di tengah kalimat: {'ya' if ak else 'tidak'} | memotong tabel: {'ya' if tb else 'tidak'}") + L.kode(isi) + L.spasi(4) + L.h1("Kesimpulan") + L.p(kesimpulan) + L.halaman_baru() + L.h1("Lampiran: kode lab1_chunking.py") + L.kode(open(__file__, encoding="utf-8").read()) + L.simpan() + print(f"\nLaporan: {os.path.basename(keluar)}") + + +def main(): + # Argumen opsional: nama satu/lebih PDF. Tanpa argumen, ketiga PDF diproses. + daftar = sys.argv[1:] or DAFTAR_PDF + for i, nama in enumerate(daftar, 1): + jalankan(os.path.basename(nama), i) + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/lab_rag/lab2_indeks_cari.py b/lab_rag/lab2_indeks_cari.py new file mode 100644 index 0000000..54e2e53 --- /dev/null +++ b/lab_rag/lab2_indeks_cari.py @@ -0,0 +1,276 @@ +"""Lab 2 - Bangun indeks & cari (25 menit). + +1. Letakkan 2-3 PDF di folder dokumen/, jalankan indeks, pastikan tiap file melaporkan jumlah chunk. +2. Ajukan 5 pertanyaan dengan query(); periksa apakah chunk teratas benar-benar relevan. +3. Ajukan 2 pertanyaan berparafrase; apakah pencarian semantik tetap menemukannya? + +Versi ini memakai ketiga PDF tentang kecerdasan buatan: + 1_Pengenalan_Kecerdasan_Buatan.pdf + 2_Machine_Learning_dan_Deep_Learning.pdf + 3_Etika_Risiko_dan_Masa_Depan_AI.pdf +Jika belum ada di folder dokumen/, skrip menyalinnya dari folder skrip atau folder kerja. +""" +import io +import os +import re +import shutil +import sys +from contextlib import redirect_stdout + +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +from laporan_utils import Laporan +from rag_utils import FOLDER_DOKUMEN, bangun_indeks, query + +BASE = os.path.dirname(os.path.abspath(__file__)) +UKURAN, OVERLAP = 1000, 0.15 + +DAFTAR_PDF = [ + "1_Pengenalan_Kecerdasan_Buatan.pdf", + "2_Machine_Learning_dan_Deep_Learning.pdf", + "3_Etika_Risiko_dan_Masa_Depan_AI.pdf", +] + +# kw = kata kunci yang HARUS ada (semuanya) di sebuah chunk agar dianggap relevan +# file = PDF tempat jawaban sebenarnya berada (dipakai untuk memeriksa kunci jawaban) +PERTANYAAN = [ + {"q": "Siapa yang memperkenalkan istilah kecerdasan buatan dan pada tahun berapa?", + "kw": ["McCarthy", "1956"], "file": DAFTAR_PDF[0]}, + {"q": "Siapa juara Go yang dikalahkan oleh AlphaGo?", + "kw": ["AlphaGo", "Lee Sedol"], "file": DAFTAR_PDF[0]}, + {"q": "Apa itu overfitting dan apa cirinya?", + "kw": ["overfitting", "data latih"], "file": DAFTAR_PDF[1]}, + {"q": "Arsitektur jaringan saraf apa yang dipakai untuk mengolah gambar?", + "kw": ["CNN", "Convolutional"], "file": DAFTAR_PDF[1]}, + {"q": "Apa saja isu etika utama dalam penggunaan AI?", + "kw": ["Bias dan diskriminasi", "Privasi"], "file": DAFTAR_PDF[2]}, +] +PARAFRASE = [ + {"q": "Mengapa model bahasa kadang memberi jawaban yang terdengar meyakinkan padahal salah?", + "kw": ["halusinasi"], "file": DAFTAR_PDF[2], + "catatan": "Teks memakai kata 'halusinasi'; pertanyaan memakai 'terdengar meyakinkan padahal salah'."}, + {"q": "Metode belajar mesin lewat coba-coba dengan imbalan dan sanksi itu namanya apa?", + "kw": ["Reinforcement"], "file": DAFTAR_PDF[1], + "catatan": "Teks memakai 'percobaan', 'hadiah', 'hukuman'; pertanyaan memakai 'coba-coba', 'imbalan', 'sanksi'."}, +] + + +# --------------------------------------------------------------------------- utilitas + +def siapkan_dokumen(): + """Pastikan ketiga PDF ada di FOLDER_DOKUMEN; salin dari folder skrip/kerja bila belum ada.""" + os.makedirs(FOLDER_DOKUMEN, exist_ok=True) + for nama in DAFTAR_PDF: + tujuan = os.path.join(FOLDER_DOKUMEN, nama) + if os.path.isfile(tujuan): + continue + for d in (BASE, os.getcwd()): + asal = os.path.join(d, nama) + if os.path.isfile(asal): + shutil.copy(asal, tujuan) + print(f" disalin: {nama} -> {FOLDER_DOKUMEN}") + break + else: + print(f" [PERINGATAN] {nama} tidak ditemukan di {FOLDER_DOKUMEN}, {BASE}, maupun {os.getcwd()}") + + +def rapikan(t): + """Buang baris footer 'Halaman N' dan ratakan spasi/baris baru agar kata kunci lintas baris tetap cocok.""" + t = re.sub(r"^[ \t]*Halaman \d+[ \t]*$", " ", t, flags=re.MULTILINE) + return " ".join(t.split()).lower() + + +def cocok_kata_kunci(teks, kw): + """True bila SEMUA kata kunci ada di teks (tanpa peduli huruf besar/kecil dan pemisah baris).""" + t = rapikan(teks) + return all(k.lower() in t for k in kw) + + +def ringkas(t, n=150): + t = " ".join(t.split()) + return t if len(t) <= n else t[:n] + "..." + + +def ya(x): + return "ya" if x else "tidak" + + +def sumber(a): + return f"{a['file']}#{a['no']}" if a else "-" + + +def jalankan(indeks, daftar, k=3): + hasil = [] + for s in daftar: + atas = query(indeks, s["q"], k) + rel = [cocok_kata_kunci(a["teks"], s["kw"]) for a in atas] + hasil.append((s, atas, rel)) + return hasil + + +def top1(rel): + return bool(rel) and rel[0] + + +def periksa_kunci(idx, daftar): + """Validasi soal: berapa chunk di indeks yang memuat semua kata kunci, dan di file mana? + Soal yang kuncinya tidak ada di chunk mana pun tidak mungkin dijawab, jadi harus ketahuan.""" + hasil = [] + for s in daftar: + ada = [i for i, c in enumerate(idx.chunks) if cocok_kata_kunci(c, s["kw"])] + file_ada = sorted({idx.meta[i]["file"] for i in ada}) + hasil.append((s, len(ada), file_ada)) + return hasil + + +def peringkat_relevan(idx, s): + """Peringkat chunk relevan pertama di SELURUH indeks (None bila tidak ada).""" + semua = query(idx, s["q"], len(idx.chunks)) + for r, a in enumerate(semua, 1): + if cocok_kata_kunci(a["teks"], s["kw"]): + return r + return None + + +# --------------------------------------------------------------------------- utama + +def main(): + # ---- Langkah 1 + print("=== Langkah 1: membangun indeks ===") + siapkan_dokumen() + buf = io.StringIO() + with redirect_stdout(buf): + idx = bangun_indeks(ukuran=UKURAN, overlap=OVERLAP, backend="auto") + log_indeks = buf.getvalue() + print(log_indeks) + idx_leksikal = bangun_indeks(ukuran=UKURAN, overlap=OVERLAP, backend="tfidf", verbose=False) + + per_file = {} + for m in idx.meta: + per_file[m["file"]] = per_file.get(m["file"], 0) + 1 + hilang = [f for f in DAFTAR_PDF if per_file.get(f, 0) == 0] + for f, n in per_file.items(): + print(f" {f}: {n} chunk") + if hilang: + print(" [PERINGATAN] tidak ada chunk dari: " + ", ".join(hilang)) + if not idx.chunks: + raise SystemExit("Indeks kosong: tidak ada teks yang terbaca dari folder dokumen/.") + + # Validasi soal: kunci jawaban harus benar-benar ada di korpus + kunci = periksa_kunci(idx, PERTANYAAN + PARAFRASE) + soal_cacat = [] + for s, n, file_ada in kunci: + status = f"{n} chunk memuat kunci, di {', '.join(file_ada) or '-'}" + if n == 0 or s["file"] not in file_ada: + soal_cacat.append(s["q"]) + status += " <-- [PERINGATAN] kunci tidak ada di file yang diharapkan" + print(f" soal: {s['q'][:60]}... | {status}") + + # ---- Langkah 2 + print("\n=== Langkah 2: 5 pertanyaan ===") + h2 = jalankan(idx, PERTANYAAN) + for s, atas, rel in h2: + print(f"\nQ: {s['q']} (kata kunci: {s['kw']})") + for r, (a, ok) in enumerate(zip(atas, rel), 1): + print(f" #{r} skor={a['skor']:.3f} {sumber(a)} relevan={ok} | {ringkas(a['teks'])}") + n_top1 = sum(top1(rel) for _, _, rel in h2) + n_top3 = sum(any(rel) for _, _, rel in h2) + n_soal = len(PERTANYAAN) + + # ---- Langkah 3 + print("\n=== Langkah 3: parafrase ===") + sem = jalankan(idx, PARAFRASE) + lek = jalankan(idx_leksikal, PARAFRASE) + for (s, a1, r1), (_, a2, r2) in zip(sem, lek): + print(f"\nQ: {s['q']}") + print(f" {idx.backend}: top1 relevan={top1(r1)} top3 relevan={any(r1)} | {sumber(a1[0] if a1 else None)}") + print(f" tfidf : top1 relevan={top1(r2)} top3 relevan={any(r2)} | {sumber(a2[0] if a2 else None)}") + n_par = len(PARAFRASE) + + # ---- Kesimpulan: setiap klaim dihitung dari data + sem_top3 = sum(any(r) for _, _, r in sem) + lek_top3 = sum(any(r) for _, _, r in lek) + sem_top1 = sum(top1(r) for _, _, r in sem) + lek_top1 = sum(top1(r) for _, _, r in lek) + kes = (f"Pada {n_soal} pertanyaan langsung, chunk peringkat 1 relevan pada {n_top1}/{n_soal} pertanyaan dan " + f"salah satu dari 3 chunk teratas relevan pada {n_top3}/{n_soal}. Pada {n_par} pertanyaan parafrase, " + f"backend '{idx.backend}' menemukan chunk relevan di peringkat 1 pada {sem_top1}/{n_par} dan di 3 " + f"teratas pada {sem_top3}/{n_par}, sedangkan pembanding TF-IDF {lek_top1}/{n_par} dan " + f"{lek_top3}/{n_par}. ") + + gagal = [(s, n) for (s, atas, rel), (_, n, _) in zip(h2, kunci[:n_soal]) if not top1(rel)] + for s, n in gagal: + r = peringkat_relevan(idx, s) + if n == 0: + kes += (f'Untuk "{s["q"]}", tidak ada satu chunk pun yang memuat semua kata kunci ' + "(jawaban terbelah di batas chunk atau kata kunci keliru). ") + elif r is None: + kes += f'Untuk "{s["q"]}", chunk relevan tidak muncul sama sekali dalam peringkat indeks. ' + else: + kes += (f'Untuk "{s["q"]}", chunk relevan pertama baru muncul di peringkat {r} dari ' + f"{len(idx.chunks)} chunk. ") + if not gagal: + kes += "Semua pertanyaan langsung menemukan chunk relevan di peringkat 1. " + + if sem_top1 == lek_top1 and sem_top3 == lek_top3: + kes += ("Pada parafrase ini, hasil semantik dan TF-IDF sama, sehingga tes ini belum membedakan " + "keduanya; gunakan parafrase yang tidak berbagi kata atau akar kata dengan teks untuk " + "menguji kemampuan semantik. ") + elif (sem_top1, sem_top3) > (lek_top1, lek_top3): + kes += "Pada parafrase ini, pencarian semantik lebih unggul daripada TF-IDF. " + else: + kes += "Pada parafrase ini, TF-IDF justru sama baik atau lebih baik daripada pencarian semantik. " + kes += (f"Korpus hanya {len(idx.chunks)} chunk dari {len(per_file)} file, sehingga satu pertanyaan " + "mengubah persentase cukup besar. ") + if soal_cacat: + kes += "Perhatian: kunci jawaban tidak ditemukan di file yang diharapkan untuk soal: " + \ + "; ".join(f'"{q}"' for q in soal_cacat) + ". " + if idx.backend == "lsa": + kes += ("Catatan: backend LSA hanya semantik ringan (hubungan antar kata dipelajari dari korpus yang " + "kecil), sehingga parafrase yang tidak berbagi kata akan sulit. Untuk hasil lebih kuat, pasang " + "sentence-transformers; kode ini otomatis memakainya.") + kes = kes.strip() + print("\nKesimpulan:", kes) + + # ---- Laporan PDF + L = Laporan(os.path.join(BASE, "Lab2_Indeks_dan_Pencarian.pdf"), "Lab 2 - Bangun Indeks & Cari", + f"ukuran chunk {UKURAN}, overlap {int(OVERLAP * 100)}%, backend: {idx.backend}") + L.h1("Langkah 1. Membangun indeks") + L.p(f"{len(per_file)} PDF berada di folder dokumen/. Setiap file melaporkan jumlah chunk-nya:") + L.tabel([["File", "Jumlah chunk"]] + [[f, n] for f, n in per_file.items()] + [["Total", len(idx.chunks)]], + [9 * 28.35, 4 * 28.35]) + if hilang: + L.p("Peringatan: tidak ada chunk dari " + ", ".join(hilang) + ".") + L.kode(log_indeks.rstrip()) + L.h1("Langkah 2. Lima pertanyaan dan pemeriksaan chunk teratas") + L.p("Sebuah chunk dianggap relevan bila memuat semua kata kunci jawaban (huruf besar/kecil dan " + "pemisah baris diabaikan). Tabel menunjukkan 3 chunk teratas.") + for s, atas, rel in h2: + L.h2(s["q"]) + L.tabel([["Peringkat", "Skor", "Sumber", "Relevan?", "Cuplikan"]] + + [[r, f"{a['skor']:.3f}", sumber(a), ya(ok), ringkas(a["teks"], 140)] + for r, (a, ok) in enumerate(zip(atas, rel), 1)], + [1.6 * 28.35, 1.3 * 28.35, 3.8 * 28.35, 1.6 * 28.35, 8.7 * 28.35]) + L.p(f"Ringkasan: chunk peringkat 1 relevan pada {n_top1}/{n_soal} pertanyaan; ada chunk relevan di 3 teratas " + f"pada {n_top3}/{n_soal}.") + L.h1("Langkah 3. Pertanyaan berparafrase") + L.p("Dua pertanyaan memakai kata yang berbeda dari teks dokumen. Dibandingkan: pencarian semantik " + f"({idx.backend}) vs TF-IDF.") + baris = [["Pertanyaan", "Catatan", f"{idx.backend}: top1 / top3", "TF-IDF: top1 / top3"]] + for (s, a1, r1), (_, a2, r2) in zip(sem, lek): + baris.append([s["q"], s["catatan"], f"{ya(top1(r1))} / {ya(any(r1))}", f"{ya(top1(r2))} / {ya(any(r2))}"]) + L.tabel(baris, [5 * 28.35, 6 * 28.35, 3 * 28.35, 3 * 28.35]) + for (s, a1, r1), _ in zip(sem, lek): + if a1: + L.p(f"Chunk teratas untuk \"{s['q']}\": {sumber(a1[0])} (skor {a1[0]['skor']:.3f})") + L.kode(ringkas(a1[0]["teks"], 400)) + L.h1("Kesimpulan") + L.p(kes) + L.halaman_baru() + L.h1(f"Lampiran: kode {os.path.basename(__file__)}") + L.kode(open(__file__, encoding="utf-8").read()) + L.simpan() + print("\nLaporan: Lab2_Indeks_dan_Pencarian.pdf") + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/lab_rag/lab3_hit_at_k.py b/lab_rag/lab3_hit_at_k.py new file mode 100644 index 0000000..5f84f43 --- /dev/null +++ b/lab_rag/lab3_hit_at_k.py @@ -0,0 +1,274 @@ +"""Lab 3 - Ukur Hit@k (25 menit). + +1. 15 pertanyaan uji beserta kata kunci jawaban dari dokumen. +2. hit_at_k untuk k = 1, 3, 5 pada dua koleksi dengan ukuran chunk berbeda. +3. Kesimpulan 3-4 kalimat: ukuran terbaik, pertanyaan yang gagal, dugaan penyebab. + +Versi ini memakai ketiga PDF tentang kecerdasan buatan (lihat DAFTAR_PDF). +""" +import os +import re +import shutil +import sys + +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt + +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +from laporan_utils import Laporan +from rag_utils import FOLDER_DOKUMEN, baca_pdf, bangun_indeks, query + +BASE = os.path.dirname(os.path.abspath(__file__)) +OVERLAP = 0.15 +UKURAN = (500, 1000) # dua koleksi yang dibandingkan +KS = (1, 3, 5) + +P1 = "1_Pengenalan_Kecerdasan_Buatan.pdf" +P2 = "2_Machine_Learning_dan_Deep_Learning.pdf" +P3 = "3_Etika_Risiko_dan_Masa_Depan_AI.pdf" +DAFTAR_PDF = [P1, P2, P3] + +# q = pertanyaan, kw = kata kunci yang harus ada (semuanya) di chunk jawaban, +# jenis = langsung (kata pertanyaan mirip teks) / parafrase (kata sengaja berbeda), +# file = PDF tempat jawaban berada. 5 soal per dokumen. +SOAL = [ + {"q": "Siapa yang memperkenalkan istilah kecerdasan buatan pada Konferensi Dartmouth?", + "kw": ["McCarthy"], "jenis": "langsung", "file": P1}, + {"q": "Siapa yang mengusulkan Tes Turing?", + "kw": ["Alan Turing"], "jenis": "langsung", "file": P1}, + {"q": "Mesin buatan IBM yang menundukkan Kasparov di papan catur bernama apa?", + "kw": ["Deep Blue"], "jenis": "parafrase", "file": P1}, + {"q": "Jenis AI yang hanya mampu mengerjakan satu tugas spesifik disebut apa?", + "kw": ["Narrow AI"], "jenis": "parafrase", "file": P1}, + {"q": "Apa itu Natural Language Processing?", + "kw": ["pembuatan bahasa manusia"], "jenis": "langsung", "file": P1}, + {"q": "Apa itu overfitting?", + "kw": ["hafal data latih"], "jenis": "langsung", "file": P2}, + {"q": "Algoritma mana yang dipakai untuk membagi data ke dalam kelompok-kelompok?", + "kw": ["K-Means"], "jenis": "parafrase", "file": P2}, + {"q": "Arsitektur apa yang dipakai untuk pengolahan gambar dan video?", + "kw": ["CNN"], "jenis": "langsung", "file": P2}, + {"q": "Apa sebutan untuk model yang terlalu sederhana sehingga gagal menangkap pola?", + "kw": ["Underfitting"], "jenis": "parafrase", "file": P2}, + {"q": "Arsitektur apa yang menjadi dasar model bahasa besar?", + "kw": ["Transformer"], "jenis": "langsung", "file": P2}, + {"q": "Apa istilah untuk informasi keliru yang disampaikan model bahasa dengan nada meyakinkan?", + "kw": ["Halusinasi"], "jenis": "parafrase", "file": P3}, + {"q": "Apa yang dimaksud dengan pelatihan ulang keterampilan?", + "kw": ["reskilling"], "jenis": "langsung", "file": P3}, + {"q": "Mengapa keputusan penting tidak boleh diserahkan sepenuhnya kepada mesin?", + "kw": ["Pengawasan manusia"], "jenis": "parafrase", "file": P3}, + {"q": "Teknologi apa yang menjalankan model langsung di perangkat milik pengguna?", + "kw": ["on-device"], "jenis": "parafrase", "file": P3}, + {"q": "Isu etika apa yang muncul dari pemakaian karya orang lain sebagai bahan pelatihan model?", + "kw": ["Hak cipta"], "jenis": "parafrase", "file": P3}, +] + + +# --------------------------------------------------------------------------- utilitas + +def siapkan_dokumen(): + """Pastikan ketiga PDF ada di FOLDER_DOKUMEN; salin dari folder skrip/kerja bila belum ada.""" + os.makedirs(FOLDER_DOKUMEN, exist_ok=True) + for nama in DAFTAR_PDF: + tujuan = os.path.join(FOLDER_DOKUMEN, nama) + if os.path.isfile(tujuan): + continue + for d in (BASE, os.getcwd()): + asal = os.path.join(d, nama) + if os.path.isfile(asal): + shutil.copy(asal, tujuan) + print(f" disalin: {nama} -> {FOLDER_DOKUMEN}") + break + else: + print(f" [PERINGATAN] {nama} tidak ditemukan di {FOLDER_DOKUMEN}, {BASE}, maupun {os.getcwd()}") + + +def rapikan(t): + """Buang baris footer 'Halaman N', ratakan spasi/baris baru, huruf kecil.""" + t = re.sub(r"^[ \t]*Halaman \d+[ \t]*$", " ", t, flags=re.MULTILINE) + return " ".join(t.split()).lower() + + +def cocok_kw(teks, kw): + """True bila SEMUA kata kunci ada di teks (abaikan huruf besar/kecil dan pemisah baris).""" + t = rapikan(teks) + return all(k.lower() in t for k in kw) + + +STOPWORD = {"yang", "untuk", "dengan", "dalam", "pada", "dari", "atau", "dapat", "adalah", "apakah", "apa", + "siapa", "mana", "bagaimana", "mengapa", "tidak", "juga", "sebagai", "oleh", "kepada", "akan", + "data", "model", "itu", "ini", "serta", "agar", "karena", "hanya", "lebih"} + + +def kata(t): + """Kata bermakna (>=4 huruf, bukan kata tugas) untuk menghitung kemiripan kosakata.""" + return set(re.findall(r"[a-z]{4,}", rapikan(t))) - STOPWORD + + +def peringkat(idx, s): + """Peringkat chunk pertama yang memuat semua kata kunci di SELURUH indeks (None bila tidak ada).""" + for r, a in enumerate(query(idx, s["q"], len(idx.chunks)), 1): + if cocok_kw(a["teks"], s["kw"]): + return r + return None + + +def hit_at_k(rank_list, k): + """Proporsi soal yang chunk relevannya muncul di k teratas.""" + return sum(r is not None and r <= k for r in rank_list) / len(rank_list) + + +def diagnosis(idx, s, r, k=5): + """Penyebab gagal, dihitung dari data indeks (bukan tebakan).""" + ada = [c for c in idx.chunks if cocok_kw(c, s["kw"])] + if not ada: + return "kata kunci terbelah di batas chunk (tidak ada satu chunk pun yang memuatnya utuh)" + bersama = kata(s["q"]) & kata(ada[0]) + info = (f"pertanyaan berbagi {len(bersama)} kata bermakna dengan chunk jawaban" + + (f": {', '.join(sorted(bersama))}" if bersama else "")) + return f"chunk jawaban ada tetapi di peringkat {r} (> {k}); {info}" + + +# --------------------------------------------------------------------------- utama + +def main(): + print("=== Persiapan dokumen ===") + siapkan_dokumen() + + # Sanity check 1: setiap kata kunci ada di PDF yang dimaksud + teks_file = {} + for f in DAFTAR_PDF: + p = os.path.join(FOLDER_DOKUMEN, f) + teks_file[f] = baca_pdf(p) if os.path.isfile(p) else "" + salah = [s for s in SOAL if not cocok_kw(teks_file.get(s["file"], ""), s["kw"])] + for s in salah: + print(f" [PERINGATAN] kata kunci {s['kw']} tidak ada di {s['file']}: {s['q']}") + if salah: + raise SystemExit("Perbaiki kata kunci pada SOAL lebih dulu; soal tersebut tidak mungkin terjawab.") + + koleksi, ranks, hasil = {}, {}, {} + for u in UKURAN: + print(f"\n=== Koleksi ukuran {u} ===") + koleksi[u] = bangun_indeks(ukuran=u, overlap=OVERLAP, backend="auto") + ranks[u] = [peringkat(koleksi[u], s) for s in SOAL] + hasil[u] = {k: hit_at_k(ranks[u], k) for k in KS} + print({f"Hit@{k}": round(v, 3) for k, v in hasil[u].items()}) + # Sanity check 2: kata kunci utuh dalam minimal satu chunk (batas atas Hit@k) + terbelah = [i for i, s in enumerate(SOAL, 1) if not any(cocok_kw(c, s["kw"]) for c in koleksi[u].chunks)] + if terbelah: + print(f" [PERINGATAN] soal no. {terbelah} tidak punya chunk yang memuat kata kunci utuh " + f"pada ukuran {u}; Hit@k tidak mungkin 1.0") + backend = koleksi[UKURAN[0]].backend + n_chunk = {u: len(koleksi[u].chunks) for u in UKURAN} + n_soal = len(SOAL) + n_lang = sum(s["jenis"] == "langsung" for s in SOAL) + n_para = n_soal - n_lang + + # ---- kesimpulan: setiap klaim dihitung dari data + a, b = UKURAN + kunci = lambda u: (hasil[u][5], hasil[u][3], hasil[u][1]) + terbaik = a if kunci(a) > kunci(b) else b if kunci(b) > kunci(a) else None + fmt = lambda u: "/".join(f"{hasil[u][k]:.2f}" for k in KS) + if terbaik: + lain = b if terbaik == a else a + s1 = (f"Ukuran {terbaik} karakter lebih baik: Hit@1/3/5 = {fmt(terbaik)} dibanding {fmt(lain)} pada " + f"ukuran {lain}.") + else: + s1 = f"Kedua ukuran seimbang: Hit@1/3/5 = {fmt(a)} (ukuran {a}) dan {fmt(b)} (ukuran {b})." + + gagal = {u: [i for i, r in enumerate(ranks[u], 1) if r is None or r > 5] for u in UKURAN} + s2 = "Pada k=5, pertanyaan yang gagal: " + "; ".join( + f"ukuran {u} -> " + (", ".join(f"no. {i}" for i in gagal[u]) if gagal[u] else "tidak ada") + for u in UKURAN) + "." + + penyebab = {(u, i): diagnosis(koleksi[u], SOAL[i - 1], ranks[u][i - 1]) + for u in UKURAN for i in gagal[u]} + print("\nDiagnosis gagal (k=5):") + for (u, i), c in penyebab.items(): + print(f" ukuran {u}, no. {i} ({SOAL[i - 1]['q']}): {c}") + if penyebab: + s3 = "Dugaan penyebab (dari diagnosis otomatis): " + "; ".join( + f"ukuran {u} no. {i} - {c}" for (u, i), c in penyebab.items()) + "." + else: + s3 = "Tidak ada kegagalan pada k=5, sehingga tidak ada penyebab yang perlu dianalisis." + + # per jenis soal, Hit@5 dan Hit@1 + per_jenis = {} + for jenis in ("langsung", "parafrase"): + idxs = [i for i, s in enumerate(SOAL) if s["jenis"] == jenis] + per_jenis[jenis] = (len(idxs), {u: (hit_at_k([ranks[u][i] for i in idxs], 1), + hit_at_k([ranks[u][i] for i in idxs], 5)) for u in UKURAN}) + + acak = "; ".join(f"ukuran {u}: {n_chunk[u]} chunk, peluang kebetulan pada k=5 sekitar {min(1, 5 / n_chunk[u]):.0%}" + for u in UKURAN) + s4 = f"Catatan: korpus hanya {len(DAFTAR_PDF)} dokumen kecil ({acak})" + if all(hasil[u][5] >= 0.999 for u in UKURAN): + s4 += ", sehingga Hit@5 yang sempurna belum membuktikan banyak; perbedaan antar ukuran lebih berarti " \ + "dilihat pada Hit@1 dan pada korpus yang lebih besar." + else: + s4 += ", sehingga satu soal saja menggeser skor sekitar " \ + f"{1 / n_soal:.0%}; gunakan korpus lebih besar sebelum menarik kesimpulan kuat." + kesimpulan = " ".join([s1, s2, s3, s4]) + print("\nKesimpulan:", kesimpulan) + + # ---- grafik + fig, ax = plt.subplots(figsize=(6.4, 3.2), dpi=150) + lebar = 0.8 / len(UKURAN) + for j, u in enumerate(UKURAN): + xs = [i + (j - (len(UKURAN) - 1) / 2) * lebar for i in range(len(KS))] + bars = ax.bar(xs, [hasil[u][k] for k in KS], lebar, label=f"ukuran {u}") + ax.bar_label(bars, fmt="%.2f", fontsize=8) + ax.set_xticks(range(len(KS)), [f"Hit@{k}" for k in KS]) + ax.set_ylim(0, 1.12) + ax.set_ylabel("proporsi soal") + ax.set_title(f"Hit@k pada {n_soal} soal (overlap {int(OVERLAP * 100)}%, backend {backend})", fontsize=10) + ax.legend(loc="lower right", fontsize=8) + fig.tight_layout() + gambar = os.path.join(BASE, "_grafik_hit_at_k.png") + fig.savefig(gambar) + plt.close(fig) + + # ---- laporan PDF + W = 28.35 + L = Laporan(os.path.join(BASE, "Lab3_Hit_at_k.pdf"), "Lab 3 - Ukur Hit@k", + f"backend: {backend} | overlap {int(OVERLAP * 100)}% | koleksi ukuran {UKURAN[0]} dan {UKURAN[1]}") + L.h1(f"Langkah 1. {n_soal} pertanyaan uji") + L.p(f"Soal dibuat dari {len(DAFTAR_PDF)} dokumen di folder dokumen/ (5 soal per dokumen). Sebuah chunk dianggap " + f"benar bila memuat semua kata kunci jawaban. Sebanyak {n_lang} soal bernada langsung dan {n_para} soal " + "diparafrase (kata-katanya sengaja berbeda dari teks).") + L.tabel([["No", "Jenis", "Pertanyaan", "Kata kunci", "File"]] + + [[i, s["jenis"], s["q"], ", ".join(s["kw"]), s["file"].split("_")[0]] for i, s in enumerate(SOAL, 1)], + [1 * W, 2 * W, 9 * W, 3.5 * W, 1.5 * W]) + L.h1("Langkah 2. Hasil Hit@k") + L.tabel([["Koleksi"] + [f"Hit@{k}" for k in KS] + ["Jumlah chunk"]] + + [[f"ukuran {u}"] + [f"{hasil[u][k]:.3f}" for k in KS] + [n_chunk[u]] for u in UKURAN], + [4 * W, 2.5 * W, 2.5 * W, 2.5 * W, 3 * W]) + L.gambar(gambar, 13) + L.h2("Hit@1 dan Hit@5 menurut jenis soal") + L.tabel([["Jenis soal", "Jumlah"] + [f"ukuran {u} (Hit@1 / Hit@5)" for u in UKURAN]] + + [[j, n] + [f"{v[u][0]:.2f} / {v[u][1]:.2f}" for u in UKURAN] for j, (n, v) in per_jenis.items()], + [3.5 * W, 2 * W, 5 * W, 5 * W]) + L.h2("Peringkat chunk pertama yang memuat jawaban, per soal") + L.p("Angka 1 berarti chunk teratas sudah benar. Angka > 5 atau '-' berarti gagal pada Hit@5.") + L.tabel([["No", "Jenis", f"Peringkat (ukuran {UKURAN[0]})", f"Peringkat (ukuran {UKURAN[1]})"]] + + [[i, s["jenis"]] + [ranks[u][i - 1] if ranks[u][i - 1] is not None else "-" for u in UKURAN] + for i, s in enumerate(SOAL, 1)], + [1.2 * W, 3 * W, 5 * W, 5 * W]) + if penyebab: + L.h2("Diagnosis soal yang gagal (k=5)") + L.tabel([["Ukuran", "No", "Pertanyaan", "Diagnosis"]] + + [[u, i, SOAL[i - 1]["q"], c] for (u, i), c in penyebab.items()], [1.5 * W, 1 * W, 6 * W, 8.5 * W]) + L.h1("Langkah 3. Kesimpulan") + L.p(kesimpulan) + L.halaman_baru() + L.h1(f"Lampiran: kode {os.path.basename(__file__)}") + L.kode(open(__file__, encoding="utf-8").read()) + L.simpan() + os.remove(gambar) + print("\nLaporan: Lab3_Hit_at_k.pdf") + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/lab_rag/laporan_utils.py b/lab_rag/laporan_utils.py new file mode 100644 index 0000000..42b40ad --- /dev/null +++ b/lab_rag/laporan_utils.py @@ -0,0 +1,76 @@ +"""Pembuat laporan PDF sederhana (reportlab) untuk ketiga lab.""" +import textwrap +from xml.sax.saxutils import escape + +from reportlab.lib import colors +from reportlab.lib.pagesizes import A4 +from reportlab.lib.styles import ParagraphStyle, getSampleStyleSheet +from reportlab.lib.units import cm +from reportlab.platypus import (Image, PageBreak, Paragraph, Preformatted, + SimpleDocTemplate, Spacer, Table, TableStyle) + + +class Laporan: + def __init__(self, path, judul, subjudul=""): + st = getSampleStyleSheet() + self.s = { + "judul": ParagraphStyle("j", parent=st["Title"], fontSize=19, spaceAfter=4), + "sub": ParagraphStyle("sj", parent=st["BodyText"], alignment=1, textColor=colors.grey, spaceAfter=14), + "h1": ParagraphStyle("h1", parent=st["Heading1"], fontSize=14, spaceBefore=12, spaceAfter=6), + "h2": ParagraphStyle("h2", parent=st["Heading2"], fontSize=11.5, spaceBefore=9, spaceAfter=4), + "p": ParagraphStyle("p", parent=st["BodyText"], fontSize=10, leading=14, spaceAfter=5), + "sel": ParagraphStyle("sel", parent=st["BodyText"], fontSize=8.5, leading=10.5), + "selb": ParagraphStyle("selb", parent=st["BodyText"], fontSize=8.5, leading=10.5, fontName="Helvetica-Bold"), + "kode": ParagraphStyle("k", fontName="Courier", fontSize=7.2, leading=8.6, + backColor=colors.whitesmoke, borderPadding=4), + "cap": ParagraphStyle("cap", parent=st["BodyText"], fontSize=8.5, textColor=colors.grey, spaceAfter=8), + } + self.doc = SimpleDocTemplate(path, pagesize=A4, leftMargin=2 * cm, rightMargin=2 * cm, + topMargin=2 * cm, bottomMargin=2 * cm, title=judul) + self.c = [Paragraph(escape(judul), self.s["judul"])] + if subjudul: + self.c.append(Paragraph(escape(subjudul), self.s["sub"])) + + def h1(self, t): self.c.append(Paragraph(escape(t), self.s["h1"])) + def h2(self, t): self.c.append(Paragraph(escape(t), self.s["h2"])) + def p(self, t): self.c.append(Paragraph(escape(t), self.s["p"])) + def spasi(self, h=6): self.c.append(Spacer(1, h)) + def halaman_baru(self): self.c.append(PageBreak()) + + def cap(self, t): self.c.append(Paragraph(escape(t), self.s["cap"])) + + def kode(self, teks, lebar=105): + baris = [] + for b in teks.expandtabs(4).split("\n"): + baris += textwrap.wrap(b, lebar, subsequent_indent=" ", drop_whitespace=False) or [""] + self.c.append(Preformatted("\n".join(baris), self.s["kode"])) + + def teks_chunk(self, teks, maks=700): + t = teks if len(teks) <= maks else teks[:maks] + " ..." + self.c.append(Preformatted(t, self.s["kode"], maxLineLength=100, newLineChars="竊オ")) + self.c.append(Spacer(1, 4)) + + def tabel(self, data, lebar=None, header=True): + d = [[Paragraph(escape(str(x)), self.s["selb"] if (header and i == 0) else self.s["sel"]) + for x in baris] for i, baris in enumerate(data)] + tb = Table(d, colWidths=lebar, repeatRows=1 if header else 0, hAlign="LEFT") + gaya = [("GRID", (0, 0), (-1, -1), 0.4, colors.grey), ("VALIGN", (0, 0), (-1, -1), "TOP")] + if header: + gaya.append(("BACKGROUND", (0, 0), (-1, 0), colors.HexColor("#e6e6e6"))) + tb.setStyle(TableStyle(gaya)) + self.c.append(tb) + self.c.append(Spacer(1, 6)) + + def gambar(self, path, lebar_cm=15): + from PIL import Image as PI + w, h = PI.open(path).size + self.c.append(Image(path, width=lebar_cm * cm, height=lebar_cm * cm * h / w)) + + def simpan(self): + def kaki(canvas, doc): + canvas.saveState() + canvas.setFont("Helvetica", 8) + canvas.setFillColor(colors.grey) + canvas.drawCentredString(A4[0] / 2, 1.1 * cm, f"Halaman {doc.page}") + canvas.restoreState() + self.doc.build(self.c, onFirstPage=kaki, onLaterPages=kaki) diff --git a/lab_rag/rag_utils.py b/lab_rag/rag_utils.py new file mode 100644 index 0000000..4f3e460 --- /dev/null +++ b/lab_rag/rag_utils.py @@ -0,0 +1,153 @@ +"""Fungsi inti RAG sederhana: baca_pdf, potong, bangun_indeks, query, hit_at_k. + +Backend embedding: + - "neural": sentence-transformers (kalau terpasang & modelnya bisa diunduh) + - "lsa" : TF-IDF n-gram karakter + TruncatedSVD (semantik ringan, offline) + - "tfidf" : TF-IDF n-gram karakter saja (pembanding berbasis kata/leksikal) + - "auto" : coba "neural", kalau gagal pakai "lsa" +""" +import glob +import os +import re + +import numpy as np +import pdfplumber +from sklearn.decomposition import TruncatedSVD +from sklearn.feature_extraction.text import TfidfVectorizer +from sklearn.preprocessing import normalize + +FOLDER_DOKUMEN = os.path.join(os.path.dirname(os.path.abspath(__file__)), "dokumen") +MODEL_NEURAL = "paraphrase-multilingual-MiniLM-L12-v2" + + +# ---------------------------------------------------------------- baca & potong +def baca_pdf(path): + """Baca seluruh teks sebuah PDF (semua halaman digabung).""" + halaman = [] + with pdfplumber.open(path) as pdf: + for p in pdf.pages: + halaman.append(p.extract_text() or "") + return "\n".join(halaman) + + +def potong_dengan_posisi(teks, ukuran=1000, overlap=0.15): + """Sliding window per karakter. Mengembalikan list (mulai, akhir, teks).""" + if not 0 <= overlap < 1: + raise ValueError("overlap harus 0 <= overlap < 1 (mis. 0.15 = 15%)") + langkah = max(1, int(ukuran * (1 - overlap))) + hasil, mulai = [], 0 + while mulai < len(teks): + akhir = min(mulai + ukuran, len(teks)) + potongan = teks[mulai:akhir].strip() + if potongan: + hasil.append((mulai, akhir, potongan)) + if akhir == len(teks): + break + mulai += langkah + return hasil + + +def potong(teks, ukuran=1000, overlap=0.15): + """Potong teks menjadi chunk berukuran `ukuran` karakter dengan overlap pecahan.""" + return [t for _, _, t in potong_dengan_posisi(teks, ukuran, overlap)] + + +def norm(s): + """Normalisasi untuk pencocokan kata kunci: huruf kecil, spasi/baris baru jadi satu spasi.""" + return re.sub(r"\s+", " ", s).lower().strip() + + +# ---------------------------------------------------------------------- indeks +class Indeks: + def __init__(self, chunks, meta, backend="auto"): + self.chunks, self.meta = chunks, meta + self.backend = self._pilih_backend(backend) + self._fit() + + def _pilih_backend(self, backend): + if backend in ("auto", "neural"): + try: + from sentence_transformers import SentenceTransformer + self._st = SentenceTransformer(MODEL_NEURAL) + return "neural" + except Exception: + if backend == "neural": + raise + return "lsa" + return backend + + def _fit(self): + if self.backend == "neural": + self.Z = np.asarray(self._st.encode(self.chunks, normalize_embeddings=True)) + return + self.vec = TfidfVectorizer(analyzer="char_wb", ngram_range=(3, 5), sublinear_tf=True) + X = self.vec.fit_transform(self.chunks) + if self.backend == "tfidf": + self.Z = normalize(X) + else: # lsa + nc = max(2, min(64, X.shape[0] - 1, X.shape[1] - 1)) + self.svd = TruncatedSVD(n_components=nc, random_state=0) + self.Z = normalize(self.svd.fit_transform(X)) + + def skor(self, pertanyaan): + if self.backend == "neural": + q = np.asarray(self._st.encode([pertanyaan], normalize_embeddings=True)) + return np.asarray(self.Z @ q.T).ravel() + q = self.vec.transform([pertanyaan]) + if self.backend == "tfidf": + q = normalize(q) + return np.asarray((self.Z @ q.T).todense()).ravel() + q = normalize(self.svd.transform(q)) + return (self.Z @ q.T).ravel() + + +def bangun_indeks(folder=FOLDER_DOKUMEN, ukuran=1000, overlap=0.15, backend="auto", verbose=True): + """Baca semua PDF di `folder`, potong, lalu bangun indeks. Mencetak jumlah chunk per file.""" + chunks, meta = [], [] + for path in sorted(glob.glob(os.path.join(folder, "*.pdf"))): + nama = os.path.basename(path) + bagian = potong(baca_pdf(path), ukuran, overlap) + if verbose: + print(f" {nama}: {len(bagian)} chunk") + for i, c in enumerate(bagian): + chunks.append(c) + meta.append({"file": nama, "no": i}) + if not chunks: + raise FileNotFoundError(f"Tidak ada PDF di {folder}") + idx = Indeks(chunks, meta, backend) + if verbose: + print(f" Total {len(chunks)} chunk | ukuran={ukuran} overlap={overlap:.0%} | backend={idx.backend}") + return idx + + +def query(indeks, pertanyaan, k=3): + """Kembalikan k chunk teratas: list dict(skor, file, no, teks).""" + s = indeks.skor(pertanyaan) + urut = np.argsort(-s)[:k] + return [{"skor": float(s[i]), "file": indeks.meta[i]["file"], "no": indeks.meta[i]["no"], + "teks": indeks.chunks[i]} for i in urut] + + +# ------------------------------------------------------------------- evaluasi +def cocok(teks, kata_kunci): + """True bila SEMUA kata kunci muncul dalam teks (tanpa peduli huruf besar/kecil).""" + t = norm(teks) + return all(norm(k) in t for k in kata_kunci) + + +def peringkat_hit(indeks, soal): + """Peringkat (mulai dari 1) chunk pertama yang memuat kata kunci; None bila tidak ada.""" + s = indeks.skor(soal["q"]) + for rank, i in enumerate(np.argsort(-s), start=1): + if cocok(indeks.chunks[i], soal["kw"]): + return rank + return None + + +def hit_at_k(indeks, daftar_soal, k): + """Proporsi soal yang chunk berisi kata kunci jawabannya masuk k teratas.""" + hit = 0 + for soal in daftar_soal: + atas = query(indeks, soal["q"], k) + hit += any(cocok(a["teks"], soal["kw"]) for a in atas) + return hit / len(daftar_soal)