From f1e735fb6d79f50e5190ef4718628555996f987a Mon Sep 17 00:00:00 2001 From: David Zhou Date: Sat, 26 Oct 2024 16:20:19 -0400 Subject: [PATCH 1/3] Added image recognition module Recipio.py utilizing gemini 1.5 flash Modified allrecipesdatabase.py with additional control flow to account for image input Added spices.jpeg for testing purposes --- backend/Recipio.py | 98 ++++++++++++++++++++++++++++++++++ backend/allrecipesdatabase.py | 55 +++++++++++-------- backend/spices.jpeg | Bin 0 -> 32743 bytes 3 files changed, 131 insertions(+), 22 deletions(-) create mode 100644 backend/Recipio.py create mode 100644 backend/spices.jpeg diff --git a/backend/Recipio.py b/backend/Recipio.py new file mode 100644 index 0000000..d4a2eb1 --- /dev/null +++ b/backend/Recipio.py @@ -0,0 +1,98 @@ +#this is gonna be the start of the file for wednesday +import pathlib +import textwrap +import google.generativeai as genai +#import allrecipesdatabase as ardb +import sys; +#"set the environment variable, Replace /path/to/your/credentials.json with the actual path to your Google Cloud credentials file." +import os +#os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = '%APPDATA%\gcloud\application_default_credentials.json' +#"authenticate with google cloud" +''' +from google.oauth2 import service_account +credentials = service_account.Credentials.from_service_account_file( + 'test' +) +''' +#"create a storage client" +#from google.cloud import storage +#client = storage.Client(credentials=credentials) +import configparser +#from google.colab import userdate +from IPython.display import display +from IPython.display import Markdown + +#api key +GOOGLE_API_KEY="AIzaSyDVzXO4sbVSVPDSccjiy4Mz3NDtWIDkwVU" +genai.configure(api_key=GOOGLE_API_KEY) + +from PIL import Image +import numbers +#i just copied this off of the link, it's a helper method used to clean up response objects and return them +def to_markdown(text): + text = text.replace('•', ' *') + return Markdown(textwrap.indent(text, '> ', predicate=lambda _: True)) +#this is the function that we're gonna use to run the image recognition thing +def imager(image): + model = genai.GenerativeModel('gemini-1.5-flash') + response = model.generate_content(["Generate a list of the ingredients provided in the following image using * as bulletpoints", image], stream=False) + to_markdown(response.text) + print(response.text) + return userinput(response) +#this is the function that represents response generation +def userinput(contents): + userResponse=input("Is this what you are looking for? [Yes or No]") + if(userResponse=="No"): + #if sensitive topic or first candidate not sufficient + print("Here are alternatives or why you might not see something: ") + print(contents.candidates) + contents.prompt_feedback + elif(userResponse=="Yes"): + #the output should be an array of all the ingredients + hold=[] + ret=[] + for token in contents.text: + if((token.isalpha or token.isspace()) and not token=="*"): + hold.append(token) + #if the current token is a newline or the last element + if(token=="\n"): + ret.append(''.join(hold[:-1])) + hold=[] + #if(token is contents.text[-1]): + #ret.append(''.join(hold)) + print(ret) + for i,x in enumerate(ret): + if(x=='' or len(x)==1 or len(x)==2): + ret.pop(i) + return ret + else: + #potential solution: gen_recipe(image)? + print("Please enter either Yes or No") + userinput(contents) +#This is the function where you interact with the backend (aka the allrecipesdatabase) +def store(image): + #hold holds the resulting array with parsed ingredients + hold=imager(image) + sys.stdin="PICTURE\n"+hold + #ardb.main() +def process_image(image): + image.show() # Display the processed image +''' +client = storage.Client() +bucket = client.get_bucket('Downloads') +blob = bucket.get_blob('spices.jpeg') +blob.download_to_filename('spices.jpeg') +''' +def preload(): + image_path = "backend\\spices.jpeg" + input_image = Image.open(image_path) + #input_image=Image.open(sys.stdin) + process_image(input_image) + arr=imager(input_image) + stream="" + hold=[] + for x in arr: + hold.append(x) + hold.append(input("Enter measurement for "+x+" (include units): ")) + return hold + #store(input_image) \ No newline at end of file diff --git a/backend/allrecipesdatabase.py b/backend/allrecipesdatabase.py index 91e8ac5..6bc812d 100644 --- a/backend/allrecipesdatabase.py +++ b/backend/allrecipesdatabase.py @@ -1,44 +1,55 @@ from allrecipes import AllRecipes import pandas as pd - -def getIngredientList(prompt, include_measurement=True): +import Recipio as rec +import sys +def getIngredientList(prompt, image,include_measurement=True): """Ask user for ingredients repeatedly to construct a list. param: prompt String that will ask user if they want to include or exclude ingredients. param: include_measurement Boolean to determine if measurements are needed. """ print(prompt) user_dict = {} - - while True: - ingredient = input("Enter ingredient (or press Enter to stop): ") - if not ingredient: # Stop if ingredient is empty - print("Ending list...") - break + #if image recognition was not used + if(not image): + while True: + ingredient = input("Enter ingredient (or press Enter to stop): ") + if not ingredient: # Stop if ingredient is empty + print("Ending list...") + break # Ask for measurement if including ingredients - if include_measurement: - while True: - measurement = input("Enter measurement for {ingredient} (include units): ") - if measurement: # Only accept non-empty measurement - break - print("Measurement cannot be empty. Please provide a value.") - else: - measurement = None # No measurement for excluded ingredients + if include_measurement: + while True: + measurement = input("Enter measurement for {ingredient} (include units): ") + if measurement: # Only accept non-empty measurement + break + print("Measurement cannot be empty. Please provide a value.") + else: + measurement = None # No measurement for excluded ingredients # Add to the dictionary - user_dict[ingredient] = measurement - + user_dict[ingredient] = measurement + #if image recognition was used + else: + i=0 + #while loop that loops through every other index starting with 0 + while(i)CQOkAb?0m2?Pkzi%8W_LRETEx}b>kUZo3!E)YT!q=bMJX#%43BAoz2 zP(XugHqDRs&;ZtalOBcmY%;T?r=#g za_{{I?SGK{zXKNb{|njw0{g#lO#>)Fz?+8$q6NqUmb41!cl_HnbYdn4)bM~U)abq{ z+l9qp-*#pM37H!F4*=dJ)+Lx{<8D6Hg5GFc;PVW}-jEK_y&0>EGTce=N z5J*oTfI+n(XQQ`gn6M~+iQPw>;0casx2qZ{GES!jYkF*}h89g0MJOgrN|KhHm%Y1v zs720!g`!1#P~49S$O*z2p#0(S9yu*oM5)@r!(l2DXwrr@TE1G=V@E*5v(1iu$$@^L zHX~n(B!Cbma}9{ROOw2in4b#fZf(&@bk;R5iuLe7AxZsUP|LF3)qR;aY@?zHbRvn{ zQoI0WzqhV1lmK>&>Vgip##;d&l$UQ3Qar7fo4p1^*(+HW>xjrC{nIaOXGtI%4BdV9 z5%*%*2i&6Sxf14;ghIC&0!1wjI79BZ2SrjRq}%QMl~2`AR$-E2*ELP?mq}n3*$jN< z!RVHqND4^8{FOFjs83b}IY=Ec7IOW7I$Ohbwzmv88cb%ts{Zi8)_;6A96K|}k#$dn z6&!NaqLm&8gQhK<;7*rv(YE{TIz|5y+^$+Q(D)3&Aw58kJw(8oM;dBzfEir~g|PN* zAC~T|?)`xeIgjF~*`YLky*>6!c}kpYxP+l=K&6h@yA|s2q!H*^5>a~ZkdlhHcH&#) zF$lr{d>Th{9ts?fGQe~}4bbM|)xQ+Ns(X9eq40s;(FBptlg`S)-qRMg-3faWS% z%aC=4ww(7=U|#H@I{U^1_Wd?;g~$`kL}2J+X7`h_AY;;dB6$t)0m7-<0LS?p9KGy` zI7ukFLd>hlN7;K2#1-kq1J!Ej-fj6B38=bPPiwY%sylSu#IHC^h)d^3*UIQ*2 z-EXbzm}jhbcR!{5;2aht9_z-Vl`L&1_dd7egRRH@!f_FtA|7aL^(A4<9+0Nbc~R^yqZB$<@hQ%8k#)d5We7icWzZ<_Aj9L$vfN|; zr-AJIqW^xKR|?AvK1K|DJAf)I@O`>hvyTzz#2bWkT7%$O2#cgnReB52GRbW!pS>8U`xj9Dv+>77CC4H~h;fMof$^l|mp zp+AGX6uM$xk6<9J!y{P>-x5|)Y_|VefsmZ&`PVMgBVf?Y{xLzxF}p%X zfCULC01`k@s*Y?=cznPj5U1r~K*F8{Sn(cIOHK}bxR=wiaSa$R(SmDHVuLdZXp4y!t%VivuQ42nP%J)=h zKf>;Z{F~+3<)aed1KTO4NP2tohY5>2UROV5cUTomo2YO1S$gVtU1`I44q%eB?&!tYvJ;zyRPC@&}LVX zC>XGUqTK5iGP(x9+=6dEWt6R5@5H7S+U3vAc5nf$P^cX*)HUF!xu9?)gFnREOz@hdK?uz;WU z1mB3c_H~4(Xuo~Wga-rI<}U-j(E+%&nqZU$W()xJjq%XbSz7e(hT@fe9uX~Pui?+q zMA0P#5bI_Ydgc2VY8%IOoU4R8uj7*%f`uAyYv%gwL!!j%snWL(i_724WW^A>=ZlvR z?D6t#M#W#SbCY0`v9HSfuo!~_EJE~bME!f1i|{9dlsah6b`!dzOSVX(#F(d-}ADs9Tcj7dkjqa0)I9!{;|2ISAkVUCvY^W z??)AGuxBon_1DvN`Kev?FHqVDAp=T_1TBMSw25Uuy?I;YbX*J-dvqnzdW%naxnk8w z`;lzoy@jYGloyt)o2!T*wXKst%&y#5N^A7AAWV8CjM}lu8p0bVS{?1`6Phgk499lL zsN@=~04gafp-jU%i5e!U7`Ee?La0Xx7qMwk@&jrGX(8`j;c&QM4_WWJ?$b`#G9&dd zYW`sERbNO)=?~G=c7aj`7Yb4l{-&Y4t2e;>f*0J)`%mPE^@WFZ-L3)V9>#R|&DqB} zws-k&xrRMSaYZE5yl%o~Y~dt!r41qkv^ER&LCh8o{Z=))_cjd&L?^%4~KYNON#?&X(#_Cr_2Ip;c_IO$Z zMcLIl`uRPXZ?j57*aH<@7VBmIey@=uH7+twA5?gxE-Jrbu=3Eeg}fk2*M+V*^i?EY zonZ!9DJ6K~6}qh|1O8(L@Y-vgGsrh0D<>jzvh;V)WsE?ba9&&{Zxe~^| z;mk(2LQBK(9C_YQ`qZ)36))Rk@$N;ca*hr-xH|b?EQ@+G5(-dF&yze=WB0Q@z&2k= zJdDa6ycJfv_ilMdx1UJ_vT!gG4A4 z&#!97<~zKcnd-Uj_DxWi`1)t{3oG7vBB1JQc>AFCoryy}6=e{%b@_40H;*=APci;v z{rUm4D!7#=;~NZ`7?-G8QZft7fcR~Sc%0VNc^R6FK% zCmTX+Hj=a-0lbVse~AvNEmH7&@5GvN5#m2l0XKHM_1FrO5;}jc@Ub(UE`=Y1ONS^J zt1CN3X47(LWL%{&AYM;Ev@g}JezQ9;pO&nzuJ2^H9ajFwDW@Jq^YH~g7{pnw>2|-P zA!x;Anam@Tj^4Il81W&)%d3Xl{v!P~m=}VRFOt;QH2FQur_N77)=9mD(?1_e*K zxBV|zB1-Y#jSU5uI7OfK{ELV?SaDvW?~zOxspzlZ*6{)?FA53}^E>_sx^u6GoQ!aP zey_Oyu1-563J^m_-<=?$0-{ODC~SWf*rhddD4Je(N^RG2!VQW2w65 zp8YQ@D1F$j#_HIzTnbbrs0A`!(0>34<&XTNSSyQJHJhDdFt$RWe-q25$*w#M7@>Kx zLX9x^M!Ar1FzC85?VY`o6DSdpo-`?_GARJKadW?l{q8N6yIcdlt%&RN-{ObAst7dr z{P<<+wrBRkMrhD@s*7NBUFy<@Iw?j#=6-uyv-TdS>&MVF;Pbh=Q{mUY*kacLWJgmT zNp^D^xRUMDH{l1I+>6O{B0lLuQfKGmzlw9rGV0BGt-ZM36*5U!ThoLLNu;QeZAvk5 zN~)~kmsJJbX}|yAKYf2ti?yYvX{~gpowbd%F#6q4pwgKgG;UDQ9To# z{VT5MkqEr7SH8;)WmBe3Xa1e6?`PHgWqLnyN=V2fY2&EE???)-3-B(*??P8oGt|}< zd-!OFxwM%=i%_Q1W>qOpa!Z5TM%AHgg{7)&KRXGHNou{&*9PY&6;FSw^Yf_qwl7rS z1q=ULr4+x^kdG3w4jlK+&YgNQwt^1q62Eo(b(do)3J9PyczB}t^Js;@R(%a%S(LN^ zHI93uUp`F8Eqqc(;$BiPtx{l-2=?@s+EDih^$HCSMJ0`=iRI>+d-e6+Lo!7|ah`ckqld_sA)*kwL|Lk^4JGkbFM3f#m zF%n>icb99~8_7hQMQ1({V)O}*e1;0SVJID#bx#D*Qeha!)B!(n5{CAFXkf6e1}cml z#1{SCQG4sM=Nj<6gtDAp23G@FLH#9BeK0>uWn9I&!8!CIr(`KTM(eYP7m6~-;mXx& z#eh0Aq0;mNk~DxG=X_&i#YFbUjYN~+yyM?jK@N}TdDQWwQrpj@gcaL{g883D^QJWA z^0waiinvhAM_myMM}HjExq3u#pQu+2^Mt6tdj5kN-1;I^J{3x7JsumE{N~f~Jiim` zhBfVME7^AC-0FWTg&bYAh-()5xw<$EeDc76)0T|do(Ac@J@YO;GDzmXbBndy^)tuw zB|KN+zNaqnr3j#u`TIv->+*b6`nIY>ZsH4k=fqE6oW`KJX?A=^=47kTcb4Ig52&Xr zcYgI(?#foPMOb0jJ*jJK+Ltt&Ucnu{D3YbG#zfk{&c%sT9Ba^7T*+=($bj(qt!=X} zlPXEcG5Z)gz=kQ8XJh>OYu(Fy-w&DGwz32Z{WHB8O_HY2;u*Z5T0dz=Yeir}@t`*k zHyuEl&VBNNzh}xOBvV9DcEvU|@#P8MW#h06eCN#pgQYP?`QwQ6hEr9!{MO=aQ<1q& zZ?~j&JV5@(hDlu}O+;LlO|R5|a><$g5gkcOZNBR-K{1z1hSw?RM=qP9Kd->!ag#1D zUot0yzU+Wf(9%@mxEiHvfLG{9t*CZgqh`9*i+xf>oJQadn3&xQGbTn-8&jAJuNVHq zsDRLZ^VLsdfBH`5N>@^a=Hit_ehFK%_40JX4_|vbb^2&Mh&rSlEcwgCsmCBm^0})k zaWbf$X7UI?J3qtt?AxqftFoQ?PYI`($Wc$7@v7`dVS3;sT6AlosKw+O5MhpY%8{Ky zRMYnN{%q*`ApZvS#yr6LbD$ejOG`N}+qPrLSWF_c)5Uqwy$F35l%U&_9CBB(-|PwZ zue!{2ptlD_%CS53-|%+cqPkZa)xWZ|TG^wKBRg_K`J6ASD~UrKodFG8QaBGB>zUz8 z)s8YNC}1j^cj*I z@l(}Sgid!aU2V>~yt66`xKvR%%j~2Df%`qDIGMIy+UA-6(5N1{-$o=!s=PaTCB?h{ zsapG($8^e9?18O|%3eXbt*?v{=p+bmW)wa3`lmM^p)uR$gIh0@1{4(Ji2Pdr_JxpE zX|%vHI;8x~BWVMpN|%y3iHTs19cuw5>x5=-jk|I2nY?};##pZ<@~EOF5HS*^Xot+b zsJEK`dsXdlcYJv3q|t2mpaA%zo)?hNlrqxLExpeYudH8{$zpd7)hA7jnMwqMz!g*i z2{GO?PJ%yF>auT0R)lM>SpWB;b*C8lz=mHo7GoD2K=u38zwT9kHZ?L{N8CIEBGBxYDN6um`(KpWE%1lM9h13%gzYmi?I56{bR>09^sV5y3TCALC@Ec6Jj9 zs}#8?SM#P;Ie7|)>h4BJ$*lI``9aW|DxCAWK4f-EuKsAj!bnz*#6@H5$SiJ`=XfE* zNF=ww|4)#P=y2mLlZxEdyJz2oGTrr$-8Uicu@RS2gt-#PgPocUj*&`BGg1pypXggD z7jpl$P5G-US%tMzeqqGtAD&jvL_U8`9)FC9!WCLIi<#)StWk>gpNE^rFPGCReH$)l ztc!v_$UBWFb;k!$mq@m~m<{?4@9RsG+*A=0{2noyigv83&6oSt@%wGXSdJJS3ikTzIpQbJe1- zLk2jJ9Rc=U19+tHf~9|rNl&;|iV5tdtHF8-tcWIK!-a!`x$rQb2U2I_ObMZxzyAHg z{~L?jazqkQ9AxG@rUUig%kIe9T?588{*C28Yg3sJ0CQSpXOLR(DP z=P6lN^GDD}@>Vi2mT}Y5UZHYyfJG|gK!d+QDtxe0 z{)tt&7Du((T*`mM`@r4*JT&q(@plu{@~srqWysKm+D?y1L|wn1o>y%03;&3m7nqYz zANxA3LXo-wxq`$$iV0zgCnW{)-vQK(qUs5Afd}o|$~kj%Uc-g)v{Dd+OisD>>Um}a z=>sGcwQH*UW%aB60?Ot;czLn$7K-|v}w>o&e^*9G;%7f2e3R|#O{U7 zOZ+2CJAacIH2Sk$=)pZ{u>bme5Z0e^Iqw;AcEno#?WGQXfgyV=xOqB1Bjl9sV|0Zf{ zDSjk5ywRxLoRPe^q-OcLUQIj|p}UA#Dt)!-Q~T{@VFV4AO>ECF(WE&J9Hv_WhFmz( zullIXi5$mex>=gN`qnFAX9!q9e#RX#x^~s9eZGHx3@aiw>@tIU%ij|u`l9t1y^d7p zv6Bzvz4ec8>)+_a-MYH*4jz(w=8Ssxn_4-Bmb495M|}!vrTMw)Be_z`efca&C&28{ zrcv{Tby5y>Dhw7VJNfa3`fcnZYVKwv{{r#(=*+u|@wvhw`1Ha>YrM=?)0nC0LB@fP zX;1t{iF`22Gt(uG9;XSM&$nY$+ngz**scNDUa=n@26F3ds@)j*A!5t&hyMA~)3)b< zNa>|ahjq<3^ryFS!P)TVG^GSi=u&O@n)=Uuk1$X`$We(6?I5#_Upw(~NoiI0YRb1( zH&Zg<(?|ekm>;8jy5%%c183e`L!Iov}%0f>-G?`*11Y>Fh){$3B10v?^-tUSY$kY-hRzGvaX z)q1*C4>NxyY535$^~qK(Vc$I?Tfxw&%d+bdwA$dOI%4o^0Ae#l$lv;gz`nvGtLQkv z03xM?9t=U)Gk^xb@UKk@Mwv1q(Z$UL3L8+>xk+dF(iYmrx^3t6c-#xqW$GJrHou$Z z&uv6$^0%nPQdu;151QKXT}NhYk@E+oXUWs>HLw((FGYiR`al}tDAW39vOSjM1;9A? z;oi`yK35$`OEcIt!x#8t@Qdt_Vz+{bj`(e|NiJ+ z{r%f9ZBH@qc4rzfsK#TeDUAA{oHf{X7?!!#BXXeeQNxbq-NwJ8QuDjD_07Y(m6C;O zgCl#cV9{bG0%C|KZ5n;@Bn0B9E?{~~!oMK-u?<@IaY>@Ps=MkzNsWut13EIjUoO^q zWPD2R!MmO^%Uk*inW=vsZaX+IIN9*W+hm+3-3>)i6?n{KCYXF}nt)l?+SJ8!k)+qY zd`E!3VZ7hk?DNWlr`l~-|6FXE{h>a&%?Fr@Xpe6FR_yAVpa+J(s<*Ok#greHrfCsD zTH23DYu~V(#|=-2_q(wDDhTiIc^mm9YlC=sPfouY;< zqsni0vhr#h7E>zzNh4GsrZNfKb`;ApU&QeNbb{}GQHm*PR@j-}l{Y<9ZEXDZmsXX? zfg>jWmC!QGU5t99#(y`u+@`T5!ew>kS<;SE5!JlT8e`gts5f8ceI@%|SUA>^Ou2Qi zdI4iw`_=@ohv>b9tY>0WfzgTp0Q*jjrVr8fjw!^m^s@VY-9ldl7tm(1=Qm-<#w090 z!Wv3-xLehZCjPk|{us+Uc)_l{&{yws-9f-nC zg4k-_80N;5?1{?hg;#;WJYh&0ubG3~_)sr=K!S$fVyDPh7Y9Gnm z_V$A<$Vf9!=kES{SHv;U1ssCu4HyUG9|7a1dc2gGnJIRrF?&(){{qe;i+}`tSu{>I zd|r|VTyjyWB4_qS%2WDq2vVvd_KLUUCbOKX$vu#4ZG8ut5D@>!nY#g};}DZ4!o)92 zqsxg1IXg_B3de-^%HPyG!&CqT97wK`nV$)-u3Ct`EU2{O{d)jgy79LXi*JcTt;X}z za%8E*+a)EuB*dda`^9M5KcIuYzmL)`VgE|ds!PmZT08nMQ5~Wc3SdTSeaB8_L! z&%n$8j)J*&VdJCSPHSHoQP8`bAo=BOBf6_`c)QGBYNi)<7iVJ$+#a`2FKD?#r$U=j}y0I-kc80)(GFM+Gr-YNHTQ!H2(_0s{zJ-GbE;xxZ5$u`#V` zJ?L-fV^x&b-7?s*Ov6(OX{Nedxl8pT=@uTD2ZdV>82iioL(Fp}j1)@#f7c3U62uvchkg5$DFW!yFl1M1yMxTN7L+_o8y)B%!*-fe*S8d7U!(F+HPJ zSNMR?_QSyk?>IH%Chtd-K|QtNU>gnOD?v`Yr4kzWfp6aBFLE>QKhO-E%zt+9gzu^R z6rp6d+sp0lyK6vIg*U9s3EJ9B^FTN^5F4>@KB1FX6rC({Uw~WFpNrRtPJzpNXhHDq z_E};pGk16QmwLbHH^i9K-#@8VJU!O=%Z+nutv^g0pWVn7xZ_m6CB;37Wa6W3ojYRn z+cGHpnxg%;u%tOa0#+D_`)VjbA_0CPgll|Dch~6WRe0u43=>5e9#G7;cjhx$$G*_RO zEF(S~xCY0)tPglwrRV0ARz2gw8NMg`!+WV*eKai0GY)+o{A$BMMIGnn_&M^}OJoanV{p#nieO>*`@8Mx_BeIFoH{Pw3uQq~A#$8wIzrMY~ zq{2cyo}$S>{;|654l_DjGLVD$BB;KT@T8fo9gCDs;Q52b@{$G$_0e1&hD!(4D zkqU>uy;Ynf#AWOmtwW9$A|$9(NW1J8!cD2h24{HGBUQxJkeD686J*~InXE*%Vv+De zQix&?(+fPm6boQZvAPC$w+cj*uu=zqe}4^_3)BN9Thw!+(AC9T^MIrtDp9Qrre3fL zEBUhgWkBRDixnuf`6%rE$7ebEnB#7fy0~qHu87QXoJ;gL#O0|T2=c9b zSqCql8OsOTwl<43R$2O6dNtkT?*+Yg*v|Rd-r)qqCua7JiuEM9nLJft%Y@=yIUAK%J2Xe(v?w!EJ1p45z*1$FYTb80XsMw>?aR!sxa|B& zjq#|CwG}Y>cdQ*p0^sURis`H=(k|w`T@;A(pwRO(+SNs zmt4P)kolcDE1Vu;OBF(V1nDcRMSWLPc=S-6;kk%*Md5vEp3F)AtW=z# z$GT&0DhBHJlsA#RWX~gypLQEM9Rg0S9>f`3On=3==i{waK0)edG~ zF^aIKw5XrH<#KD{VlDTJN_`|FS{eG+quQ!&yp}V;?se$8pzR;8MA_FI++H0=&@sU> zi#4vxbvR6#55Bw$z49*SW1@H%J|k(aX>w6(WZN$Dl}f~cN4)z8A!qi|$o|t0>0ZyS z9o|+hUs-0tg(4*7sagulqzgoH&aw8+xG5%4P_X1j)YZD|!MbXT`*&D#lvK`%MZLTz zLNmawbipDDLfWuxi*L~Uttxf?gC)5^uiu>s8h&_Oe#$l92D1~>_vaugCf&1`H zZR4?W)5AN_fILtcpOG2{8PYhD~?ia}*$fM{7u$HgloFq+k z?gK?ttkgemcA~PI%3=4zyFckeY#){J3#j-mhQj4AY&D&~O@G`TnyKD5a(C~SkGt^N znBOuIaw`Jp~t{8*vt7@11I=Q$R8bt3SAjvN^X5*%i>!_9$PTdqoehofl^lMl96+ z=8kKOrBn8QoGQ?B0%OT@V%GpG<;G3r(LlS=Ww!8g&m6k9x_6q&lnWgSZu4rN(!2fk zh0-CA3&A|qZxxpdnP2~sMVuF#tzuVoZV`&X^G(5^*k#Ud_=jk~nPn5R`qUe#VK*a1 zsGKbWWq7+>YHb?rlTR_ZDV{sz_e9!nZ*Rhf4oZ_ct2#SW}Q-ac>?+xsG42uYN*9YdaY8tc2>Zjf-N=doAe zU~?8XDvZgeB2MdTL;W|4SaTyb>xjLC1B?-AitC5Q&+e%{al0g(QaIV=xfV_BVeE`< z7UX$Ryk`UvJv;tu37b#;NQrx9m|My6l~ApVjA7J)V)i3mMMy`;xjkyD~nR^ABhS%PVPUsn%b9` zL{Dn1C|zxj*G~qN z2!HmbO{1wL#{-E+We%CEu*$@oAlNAOMeD3vf0^3$+S@6842@s6{6L8Q>F_9#)xmP{ zP=K}1{@_(1q&BpkqUP8r**ybx2T%pUT?1Z>tY-cBSs>WtE`xksjXvf42AZ$Wg_tir zV_Vm7MG3#={$gl0F>6(MSbPkjU+d#d)(tU5!+#9SBM9yi212dYJzlPnF*d`bF*%hJTqRAdU?PLN1`{#i%iWdWs! z(Y>B-s}aOT*RGI1(?%vu@1hnQ+(7t`ee3y~n=P<6x|2GP15&D!Fe?UMS9y93*}6h< z%2^dGm{R00XX8;B)^&Gb13fhf*8Tyx-ttRuoqioIDmmISX(Ec91xZ2pjX7j_Y&!Rzq ze1Y0)LVh^M&Y9Sa18BamQXv|<(zO(nnrv+QesSnK4l_R~m+g0qMj(>bwwQ8*e4d6vhJ2lhQ1ukrOL#`S$6~cw)bAJfE?1tv(Z@*+E6O>JG;%j`$ED28v*fGsgjh!BO z{+wn>@C!+EKKldD0&H~As+KAqY~ja99xv2Mgtb96_uW0wJ^3)gKAdditNi;pcIuNB zmx4zc>@~9Ii4#ZL#^{OU+B9{{%GW5SHKWXX3gZ0h-wOi0d+|Yn)ivYyE5ch^IyBz7 zn?S8tLmq6IHX%@%_M^i7LzMwh>I^-PQA9~ws4=r_BNk`>eE~sXV_xD3&ZSonWjBlN zN63C<@Ux*WN8q9*ei<0bOllXhwc)rgc6---M&ok$V?glRprEn=;ZNdf>b#&_yvOz- zqusMno6%i1huIykc??zOxeiLdf@k^2>F*C!P8ZQ}HoOL34dnM>*~sIz0S$?? z2^ih4eS@=6+OD#DvrL(MxpA%pCI@*6A?&)5ldZZWKK;zzj+h1cT&c%TQfY2;cvi$- z6B(?h_6lDzAI@wxv(p!^DMzj3k6Uaj?GRCD!~3_dB}YhqG!N>_F$u#vaG^w#>N}vz zd)sH@FRuy%OH`g^^+%xIjb84S>>63uLi&sQcqvq}zq^`O(4)|@Gyu0^W=05k= z);gnn^W3UQ^@`wHcCh*xTM*+s^S2^n)v-jTD@m+P!2scv zV17vzLhZO&VeN2mthA;M6elW?@o^P?2vw#D_z`AY5Y71(2c~{MGE!3VGg=8(s z`bqTwGQ=LrIMOef@AJj$K-Pj-OS@H7Za>J@yga^z@GPdFRz=G-KAdtQWh=mawAncL z*RD+UFF?Zp5L)dB&NBGhYG%hb;_RQFCT2(N8qf zS^CqduA(o_#(mm1o%Hn@Q0-EvFxOR(W;Ds0bSoQaNVPFx?(~whLZ9l1R?rH(pb^JC0X=`t3k3Y)_=)Z|H9(82s;%ITy1QjO<^T?V@zKMamk=kJ^ zt>2c`h(rlbb+$0Cg&wR3b#@-Q2|uY6{Q0%`RmdPFDKqbwzG){TqmSJWGoBi8-!(k3 zN%uDT=$8u0zUPuW^(*5dqSEmc@gFp(o8=rj$pTPh&mw_PwxUmtNnB^nJ@9EB!t2wZn`k*& zQi{!bfz*OpPdecmV5s-?HvwZOR4-}kGQMj4Vn;t2cwX(`#C%_Uu&<7I=im{g96N;d z-7#nEimZBZhAj;bqw$&z6u2%=)f(^m@)gGby3_qd5(RZ zxRsmrl}Y-ldM~=8?&qVT8xcY#i7e$cK!6gb3b`HL&geRKPYuzS9H?ie!bM_+Y~DeD zZ!Y@WBP~oetqX1uc@n`H8phxiTb<5ZM118@?UvMF>)Dowwm zE#yl!{*AL%W-Z+|kSQ? z1&wAB_fV8KhbmI%HZp~b+yzP>42T42D|*l^hR&>(^x;Y6zNc66m`v5>-yDufD+0rs z>)zb;S*d*4hg%Oc_@uT1>zU`5h29j$kBpyq(k(<=XxZ&xn-VG)#7$0^t&^>KU(F?} z;VN&0SB>^oW)8Z$;@K>Md6j7el!R5N#TZ(>$5XxcbCX$jYDX;)OiVjm{j;oL+K&}j zsYPHw?&PzJG68&xydac-#d_GABBW;v(A-xa%_g74(YFE`4Y;%?>g+uB*USg=xr+sa zjt0`UUpi@w>(?I;~8S#=)d^PPS&Wjw05sK%ky+I$Sc|JXv@rF{X|y$l{ymz&;S6Kx>P*wei$Pm zT*+XjrpoE6C<`>d@6R~4R(>CsUh!3@?eQxoUir}gCxs#jZwWnNr=3;xaqAKSue+PQlX6rhdMwQs`FQwwN`$-(*$Hd1{!_9(e* zwNI13%%2x}F+<4I4thKp0;vNWVK`#8j_4;c8c|#{kJzq8XHVTx>{;Ihq#48(JlzA_ zrHWq%p@ZJ1=*jN_ttJriEr!Fo7z{v-Gd4}atgbO_hD{3%49XD0Te+bC`MOF5 z40m1cY!MFx7$cgzGF6G;r=Bcf@N%4+8B_8*@#Cl`mXSno? zAwzOUV=pe$G`W%m{c2C`oE24tWkgRTdvPet*~m2G`-}ctR3z}ea&T>TV7bbTpPyjI<>5!vM z{`-HyKO%-ec^_fj74>fw)z8?4HK#Lnw?9cA%=}J#POZD*MG2R3Og1-tYIwQ3(RuGc_ z`2lP{EH#VEO{;o`7e5~+@BJf>tC6=qk1!{24OT>1e$e_Ql>*1pp6 z*SS`VwtNTS7~tsH4MGMb-50<V`)5pS+9^Fjsx> z*DOKmt9X3Ad`a7d{iY1$icjQ8*$eJ;B5s#lw#lB5rw+AeZ3}Rg7`*hDS>COTERxBU zumImd8xEPv_APbSKL(Ag@y+eCVu!rE-<_1Wh6WnioD==Ky{6yb0EFBvGoulG{o^~t-i_mzocO1s z;1UHSrn)(%Ah5r;{pZauO|K#pd$SIyXm1Z<3vB4O+?WPy_#Gv+jA%G6uS>i~llxZ; zTyFVl#x2L4l3Br^MBZ0kyNR%dA1IkUwKYi;_ zhFZHUw`jdtbRu&gT>~Lib+1|_jc>78Ez#5lb2W;@SE+S8&97a|A!M2fj(f^Ey2Tbe zmpn)2zf0wWdGy{CZS73^R%vt>iY^W-^FPhsYqbj9`Qy#c2fyF@2lyY2DdCzG>G}p; zN$PQup0+$7BIk(axhXn|#y2MhjwPGLZYnx+&hx$>%-}E@xVT2mtTxiC(X6s zoGw(b;iU4t*_kKqWRsnK+}}`_2x;Ru1F82ER+4@h$UW0(JJvio?rtXV!N6w_52ql{wdD><+N>zm~0W#S)gUZ>+(6ye!Y!+ zA*5K!NwiilXuKG)Bllzl^b@sw^RG^qt_zu`86>KiJY;gwD*}XIsSuk{M*uk79Xuct za#SkrM<+srSq7uV+$7&w>L^M9d`g@P;`DlR>3|f?l)msQLy$_nQ1EV1IhDLml-ZCtyz>biV?UNq-N?6T~a zaDf4CXtaKqT&jfJ{XJ5Q!d-1yr;$Mdqq}=;ap1k*mytcGel8UTLP$FhCVbZ58Cweg zwzp;IU3q8D$!1ps)xTu5f~%6Yi4zf z`)#%UD)yFV|7+ir%jlNqOH^Q29FfqVFpF0&N15e_DD+!R)msrCepY1R#J2q(&3*Sb zoBtbkh+4HvOB*}2sZk^LC}Que_FlDT?V>b7tSV~ntu|Goh)wNPD+o1eZ$3}@J?Hrc zo}ZqaBRMC>x$n34a9`K;8kY}CTYLJ4QVo!gi+81SX7E86Z$Xx3e$qDZEM= z(jk9M^-5y~B)l?Wh8*VUP;(t`;esbWVJPtgjfX~@dNsmuezJ+U$g z*c%)`)5r0l*CFl-?;k!#{D__=2MTv2#)Td^k&X!NQ@yg$gJr+ka zz_-DC8Okc|fjfG2p(#OLCbKpD0b`z=Uz%7T5oC%Y=(wHA0X7lPIcuYXeLZVuqjNiU zS#QC%>G9Of^Uifzz0jFWK+LvIH{KlwDK8Nq_@NQ2o_FQ(us+{VXMpqoMrrP4<#21b z+gb%V>Cljd8-CH27gxsNZlq4r$|EB}KNaT8^V85dypBpWeV7B0dUx-nm}C$@ zzKN?3CR6Zb+xM8rIDQL}UnnS3lF+KL_DJ#MC0D1Ui^LE*bp?ZsTu^BNOP5;2qhp>y zY?rJFBeS-bu`b>N;sqR^X?pUOkte%X8!f@+COJAjtEo{WJL_Ws569lT&`+lY!a%p<5JDu)EjdmxN^t zuboF+AFhG4WBwZ{M2b^2tcwlHh!5{H+;KSw@Jd|HE9BY|WI32(5Yx$FqBGp#sjK&v z{ho?WY3kqUR}%RHG0*QBHD*g7#EKVspu9VkU2sxn@iF;tjYLDblV2Ex zS?O~ceVXWqn_I3|PNY3Uy+0CA3%Wkg zQOHDWSc!)H3Jd+JT>`Ea12Hf0C`h9xt7MBMa;?Mroc{cH-Z3SP^tO-Yrz#|r#<>v8 z$np#%X(Sdbz%l$pGq^5;j>|Ax_h>Z4%#!QvDlop&8~Be>t~~%H-feHqb@1@v%Q5?| zr;^EbsCfuV)*--Gq>Gd?4o>kjZG~C~(6sbmBTp!!Es8U@C_Gw~HtEjYsP*tUlhQYu zUrzDJeMp*xro)NibVC|*sQI9{c-kZy$~+jhOjbXXW(6NT_3vI^q<&>q^TE!_y8_${ zDRi^K0^<^s62Bqt@TzF#@-X$EV4t|yXf-yIKwr`!-$eK79Yv_LHV z4;;~Vc0n=!^*Ag4wMXp5n4t0T$La=#XHFTabETWDUdKq>Mm{e61^Zj7q5ML_E= zNyfARSon0tqY4Jvz+k6$jVmVh2flxHCmP;%5>7Y!zq2NOOoTNSq^ICy!vB&${tv9P z{)pO}_J8qtlJqa^`EF(gx|wn&U0F|pu}3l@iJpBSk{ENZ+rA1(Oy zkW%n~>fxR_X)Mzo+)?W={0KthU!DrB4k4T%&Mlf({OH@<0Z` zM^pN0lI&b=Z+v$qD{Pk>UCP8FvU9CVQPh>?E?Q1%*ki+blP+=M6T>eWhxxxy1+sAj zMzg|2iLz7as;pU(%bZ5@hC%Tn#9W^Azq@4b`qFd0%Z!WrRNVZiFL8SI?Bu829815j z(4|&l?|?`Dsx3MC~sM|WnNCM&%bd2OIA z5LjO-3#t*vnythx%MO}(VZd2YQSl3^s3s$a6@zxw&TDVUV#5d)m#|1S1QwKk3(4HyYE5u2ffY^E4p}4G55UHk+Z9 zj!shAdmBHR_SL#%P^{mrh|Q=ckYuMJF#Q9qDP;DW?$DhZCl_>p$~8lhQjRc8P$_ae*n=&$+t#f z;fto9)MQ;820}@oD$ZFHHla+f>B)A@D-FlEAND6k&2{x);BvW*m6vOU~+QnFK4BC|{f-kzL z%kq19$$HsjJ&~uCv<9a33UR%)+}(*D*E+t+8wT&>6tqAAIt_d~xfU~z7b;zQDx)dE zYoFb6QoZ0{$ZyUZ(`MuG4j&poBm*dXBJ}*e`~^4DMe}PG8r&R6YctnVRak(1DY6co zG1S;*{xUBeFSZ3p(~SYhXF5rt^`>vA4p_q@TjUr1|IGrQjyEFM_zF_ zpE|+lES-TJQm?FuZmO|2IWjr{-~IyxcZz;oQ(CQdT#AB@EO^w~CDOr)9V&i)j7`6XJNexCvBbBl#9}~MlDGtamrl!VlB4@2 zvvhAIr47#>8kt|e7c7+QtSZXhhF%<|c5Uf~YWv?g&vSWaN{9{~xVWaR@CzM<*j=(t z-_9joIqQFxoB1(O_r0#c_N6Wj14fqiDDZ7_oQs=<5`~3U7(@0oDyP59h-U1P`#SBC zSM@Vnwwn<28?Tk3%LRIB<@;xoSeM4VPcD&>ZQ}m{y#E8pzzp(MoPF(tlB7TCnQW&# z>Oq%YfPvQr@V&rqe*$lpr44&p-dN9s{k=+Z2&|3&mB$7I7Q3s9ovOVTXK-UtC6j(F z&z8p5;+ac+FlrdbyFc9EPAb9voM!C~1&r_tUo4&<3kLkra7rR8A%+8Rl9zHGI?Ocl zr9}v`!U8ZFsWLYW*%yXG7IlxQX}}kMlTEjaf>`RjnG@U_U>kz8{{a>y(Pz6Ri|4;S zDWotW)4K`I$NvMA*EM{4A2z?~&iQ<5%lL&>$;jvd_K?WH5*;Djq{<~Y+lb&Xoi8j2 zPdP!Z{)u`iKNZ|CZlNuJ{(!7&V`YWvrwFZD!0fi4eQ^$x66k(36IS2zlNE5#@BGwo zanW-^Xatr#**4zD|Hh`N<(UWL5(n??kIqDN#?P69UN3sE0Foox6#nHu0O6!?WSgC5 z!;~s~?AlGUqIv=AC)WJ*y7&m`djl!1c*^6ER%|`AWG?EC)2#>zlN;tkAnD3y1C+S=b|O)7?kh>K}6w$2Szu4KUMpPgp9hKa53>c5zF~9 z?QsR1TkWt_DN%YxsH7c0m-_Z#HK&^RjYYu(D3e)c3NEI%_nL-b&8r(J_drFYkA_`V zB=*aIeD?H}LKt)a4`z)eF2`cEiSR5N)Lq5^&nnn4X~ee_C|G6xyf8^t#r0&UosN)i zH^F-J%^x<0L04|1s3LKl03#2Hy8qHX-!j~5V55Gmh5RLQ3Ev^2GX)APKb`6{Zm)Q2 zxFAE(KMJl~*YnEmh?$rnRyt4>1Ahgw-%t7Ui*Y1$jDxcU40WB#mB?8NQ$Mi>*gLzr ze0D(;+K9cu^`l$3bJwWmh{phsRgE;u*N$7oCjMqd3G@T{uTr`|1**Kyj(N|-F)5c)Ls z{I>ldD}j6=kQMYG;gr(!OHqKRVr`QWGHTKs&wbE8z5#JL#VC$kmBgA39dZ8p8hi3e z_Yy>|iI%7tGmMFhouy0Y+C%Cm}@ORZ3S z&9wau_Bu%eS2~Td@JrM5SuO|HoiH|}cHmPj4f^M{AUXS`H_DVQB7Z96o_7g4Wjqsu zyk#+}{H|onHN-R$Zip2ogSwfst~4y1J!HO*@AA3Dfo9))GY&Hcik<_cbAnZV~S-|R_vl) zqu%My%U}s!iB2OdQhYd@u5_K~BD+2Y(s<L$RN0AQ?67oJAgS|l!K4Nec;hMRu5Gp#wyxd2>X#AFq z>X6wv?3j3VEL52^g<@q@ONl~7E)2&uP4A-5);8MEhD-*>Bd(LK<9%%Nh<;a>y=g`Y z=QAAEeL5Z1%r(cU?dNhMA(-hK^GXq2=+ zD`ZyBaTz9!+n$?D-b62MS_zG;3p4ev%+F+^fLoYGPX9hw!M{i zt==?f4wrq$nf3mvBCfrb^1If0nYeHeNInB<6k-JJVyO!mQz9%^KTN0kBkG%6`CE=s z$5d=Vz)HTo@$q*O5pBbWU?^3^s}FYq#cgA=E$*IiV9W6-ajUGgUDusFqTA05$1nu>_g( zGrIG<7e$rakMq1O2xtHpGp#dB4wxQGCtu(6IH?;h19X&{CJUgAw_A~W`SXi~9o#zW z8*S@dxdEbZ>l20lAOwk4p%%l3^!w*>S(!Z^{AluJE0H8_U!ASFo}tWTEsNf1DT$m7 zWQ*bP*e4IJVKgUu@_klf??0~MQJb9yg04SY3=W=^Z!GU8o@tUwrizj!17rxRvM|cX zhc;WX$e)Ow(lz?i*~)CRxG;^N{MhIkih6Ih2Jty`=OC8 zcFdp@KoQKTzJXsHGx)BZiA)272AI`1xX(_hy%XJ#U)w}U#_TxfP<*ZSvHV(OUH$8j zsj2m2ggUCBi4S(H@1t1;noyqvQw-49$YhK)!C%WUM^Ud)NR1nt#G5&I5V>~Z!1&Ra z;e|;^>_xmP5Zlh2c~k+@5NG>kf`9kJ09RjfWxMQ8%@&fl6!2Z^k(<{kUBTXD#cdP40x`Ux*4e&=H}yU~HSZ^+C;T zTTjV@WzCQDFgsGpd{1|~(L9GxAj>MZt)+c1X^h&Kcb*WYzLJwJo-vL8_OTF$(PTSNczKKM#hsXjY~RpB9m zz}-)Vr$qC8KcI#7xj9-|#U2*JsZVSYqv&I6tfpLMhlU;-UXhn-{Y^NA2%;s4>L{+_ zgb{{F06%?=%uUW@hXPoaMW<2A)9(q4)V#=6!k9;ti8H=m*65>HEr6C!S1{J-mA>H& z%ueD%iQeTMN8?2+X_i{Gt%UHC@GHVr8(Cu{%ZAakz>_hJ>jyo~6<4P0xc$+_Z){d4 zMA+r6!GbxRx=pTU_RZJ!VdEdGS4YEAKRh!`& zD=aggok3?q7{!hAwV8ztNa%M-mR;R8bWM7YB2TZ&vb(f&KZzr|8B#-Ss7mapQX+58_-s1EYR)pVjSdM?k6m}A-7dg8e+oz6}bxXQ2&&Ey2A%0f88F2SGTL> zDzzfWkVs}g12|#l`wyTdbvz|Kf|dvhyw!;ok-V311QWkVwH%=7!x{t79#04A!tk$2 z0vM)1z;hr=N|Mawb|Q(oI;9Ur42iFb6V$&3U7G8>zR@p3AO%l>ZXNSd?hmGEh-#)ZrLQKMfMgDM4 zoefV~%^xEb`%^*U^AY{rj-O8v(XwdpEOCFG2O|@e;an50n!6s7O$_W%CfqJuH2Ix5 zBw7Hg!H#;lDEa!>FcA5(BHhY4o^H)t9=0#FCq*)P6U@K%tJ0}}<7`!cpDa8Fz9DGLJ}f0!gyJ1(gnWV3PjK_!iE zzuDGn`Vw>d8eMQxn)cFZq{7M#goiAJF515r_g~XTC)2I=6jVz+F|uj@I;P~d zdE#W4*h&pLztNw_&#T_=FY*&~P2ALYP4=C4HyJkl%M$llE4s-EEK`@_%?iGmS#lVO z9behkps7;Ta+Q~sUS7XJp;=kO#9pT@W>^lJ#?gbBgew89_{ zb_G02%LKnyVN+d?Bu&?d$i(!LNIyJgy5C|9$NN_w(=;)uxfuL-Lfnr+nr6);q_7B# zvAgsO4!?*XnI)=vI3fMRXEg0=@MKCmyOF{aYQeSIW`)7Vnct7*6ieT66zV%gI^M9K zVU|FrfZGdPy<87@H!}0N3rj&_yh;R|^ju%wnxfdijZ}LD67zVre5AdA* z5UIHYkfiC1X;cDP9vK`aN63sTduv`J?&5F{{j6#f30bg9ssG5krH;I)WwOVkyZtFEj*3_a^^UVHpwUE@L~^lYjc{d6NHr~RsO_^d5579 zdR=T4eEIoQ%*J*Q!irm8Rus>^=egDU>A65#1Ym5+ObkVX6Kw~?Dxu|^@rf0$V0AeM z86;ojl5(ri5#{7ixl2fT}2 z{ifmF8%+VObK4MH5$0x0MDQVj8jl)J95e|PV9_Ws)|FyF6XJm{3V}HGB>s=HJ3=6Vw7sp1@j3 z|I|*mJ1c^61T#m;B!v=2Tq?FSBHql__nPGT4~zyPqZ*bZNR{K~qrQAR-9nCx-v8Rc zLeb59ce6No?(6@X5-|Xx>j)0iFaPXUrr)~OX@ByK?{@6I3G>J9KnMCmi45v~#9D4p zxV_?L53Z+g|S!c&wiuX|3N&38@sO8g1pf?J|$pI?Cg=k8b=wt zM7X+U+oK)EtJNGFqW@_{6*BXy`wZ=PPaKS^_jWq+(~iene1>xw`iFym7tS+&BBEQ}DU~0-;^%jJBtvL1 zM6ATzN@F2H^^3mPk+5~f`G_LaAj>wAKJ$NAj>7hW%>XDeOKf_S8p++1_9{KwP5{RGuQ13}^4-&_wxGHeAguSoSq)z+d*&)w0LhbBkFFBul0TOHdv}* zVw!Jkypr5|Jutz!Q8IvyW)QSF!F(%z`X;adk)Uh_9o>`vmPqOoY~rxJ(8(X_TfPbK%5)&@TH1aXw6g(#ED=M zT0ZZ>oJF1Qa+Y44MSlPW4n~wD>3<)BIie99i+{-5>$zOq=l=spwp5~6ib^+=jcKQ$ zWnqAxBV19vFp-T4lOIPAGzJnHBKbi0M^VhWYcuey1V&_++!P>=iqje*icFH?ut_w3 zN>+Xd^l}{(>9bTMi{%@*j)kD9CYF~9JKrZa*uTrGY~{8Qnp9p_bsoS$F?U`Ietom} zx_FY`r{tNa1y=vWDg?Ais(ecNOl3PjMDtkyfMlNPkMYcqeBQvXsOtySaLi+K&P-(^ zX5?Z=4A&*t{~5p|s#avXjYvhrh?yA1y9Ymu?cR|hbh3|2 z0fdD~`HLoKlyoqFaTFgg&V!f*n=4>lIxU?zQM3{%IgngU1#&?B2JkHapzKD1l$0|~ ze+-O}?YPZ*h-HyWhwJnVMsy%SN_Woo=HqodA_1^TudFHLibwBPiWW4-vCr-(_pjCD zq!SCm@U<#&Y)+Hst=cpQ9Lh>Rw|_x?1_J65HY5VhfN|SfvIKaoDB3*}=`ZX$wwV-5aIhY;5(^9o^?>4-=vvz*wp z#sq)LzV$8HvGsI|>qTKUr_DKm?Zr^W=>t3Ks5o6a)`cir#|7R*b?oDoiwc-ZSUEm* z7xMIGj#I!mN8Tyt`259xfX5`9&&(1=>h=3&vz=UlT6By@!KsUhcCpyX5;Xo&Ie5nv z6mOb^MxS_Fh6QuRJX0Iu<|&=bZ2S)QT)>i9X|RHM=n6^1cf;jH#-&ike4>f?43QIY z*T!`oz7B_>e7n3Y5&d= z+|H_OqqBAv0#mbAD`LDjJaePLTdh*)^J+(W9Fp@qq7hXKU+Tdc!$I2UM5eY5=(Yuu z<~TD6ZK#tffLzRdj}Z< z(k^yH(2TJSwIoJ}FAl2tH%H);i3dF=lcjW2!u~)FXW3A0my~KYUzo^vV2moJRCgU^ z;+4!Gcj+;ebvEwiHEREKYNDh}U&XFzn#X0^We}K3e7`>bz>J$iWDBN8po(67G`EjK zBN?sXLK2d;(xe+CPKHoC52QNQ-?uo7iUWJeNg9Buml$Frnge><1&i}aveCu@XVJ}w z8*rtKV7x1A}e#F zE7KnwaL^|oz!|_gZ!?+pQ~uMDeA2djCiUPJg zFkZnO%VL>NpX7o3`s9V3k#(GPpikqP3L+R|2tw&sU1NaVjBi@fk7B4%E9I>iNfA0> z_e$?uv@#Y$j+xAXG!V0_%i5Tf9P(HFBWHNak=W&HEFz`Br5&i?-jCaal4h(R&5FINvaDb(DdeVW`1RgJRL!T#W{X}q!qRO2(`*! zfMiFgdTL#X#A*`57u(nrOT^XPeMn=WlaWy}ho7IK6E?d1xO+QmlZlSB1iLkNn~eH> zIntTD8*+J8!M80QfAZ)*fd6Sm$c!)Rg5*|}oL=LUg}_?@K3Z}JrpntayccZyLb?md z0Gvq$_aM5cqNCWJAox6l|VXga_Q0c&h5vz4aswEyc-)Nt1hBXRp$lD@1}1;< zll)q?XDSsw1^_!Hdp-}l9LXT_Mj;~OTX6(@*%)nfGX^307rcL!)OuLq_xM-0&^jU6 zN5IcHMEs=zZg>!oUAk-x(uxgRE(R;?I!04$>gwU*48P>MYNs=?Pyq5EjkSqx zrd(bFVfbDzy9~g{{$E4qr34~CxVj_0OjeGEwh3P9MSi`IK$t*WZCc%Zs{JWJ;)$ZB z)csp8eZ17-BWVCir^~kOMz3~JAZ76wLKW1 z((K<&B%r+#%rBi-&d~`xHE|BWP=8*~j&ykay_&Tvc)ytPGpw#`T-91oUqm$~IeaD- zO(mk52; zQST6{;~7kkpP?mam6!F(GZ7mMUY?yJhny@boJn_TRID_0JT_yXc*R^ml3yBXp+e3g zv?504u87v&mE@c7$(0-rL?{RTWS{?eBoRt9d-8~xV@S~oGU_?qty6k9Tg34V9t{=+ z$Gq514+7wwS4`|Q9j$+TEbNN*5DZkZYL-12sw<`8LQ+>t^-57TaFf$=7eBkSuu#Mr zz`HNr!JA@<^CzVIJ+0Tfr*}67aG@C4x_kLZQFG_1B^IL+Kxrnpz%vfjTvXih) zKz)-eToyhg5w=l$EcHq773JzD43)etbVfD{Y`wI)d}??c4Yr=kI*!{{UL=d%7zBG{ zqbIBTJ;QZRbBg~IlOENm6G&px`;6Bj<0$E0d9L85sh{Fp+J^JI67KRofm~^G@Q|U3 z)|6Q87JkKt?U0iTR2Jy@=Elq8`}K)zjOITuajCK(tAc%iIfC>ouW;sz(z&Ai*05K3 zn$@<#dOkU%Ys{UrI#|lM&fV2p=Hjai(EQozJ1gmB^DObOCk@zM@H-;EO8l+q5en9e zzK0oVLe_W3o4(~2`kWMs;$z#s*FWtKFaBP_1K|aN90X#qO=lF(QvYrx?RhEhtHk^< zJRk3Hyz5FT`e@ya)OhGHklR*jVJh44NX{8Qs-VG^4x|V=))&m<3Lp{oK3GB2fa{nn zD8GH3=WGY=1m3feED&e=d1ZU4dh>i>hwP#>2I=8P=0Bycl7F3v z@?Y!mE)8Bo% zFBDH0MqKH=Fj7n_yd@$L&^KF`9HoADUZ>Q^E6}PTaz`o^FW2T+lb#JnZE~}axVP*C z=_!i553&jI;T-VGIm}*ZG=95ccPIf5oT*9yPUiCyk#3! z^!8FB^f&U9D)~PEfl5c#F7eOGnim}PFjufe2vh5C^FHI~B4;8U6O(Upzf!0myUB;r zmF5S-l>nEuM*(9SUPdC4QDrn@e<##oEc3tYSN|es{9+5d zvZX)aN#+5gVg}e#S1X?=etz4LYG?hVX-gXkpx@1!qkr~M5FlwF1J@YN zL8}K_oxCABVF{K6YAn>9=8wm2S|uV|QdXeA66GF{b(LX9TiTyDr}Vxn03a3Mens&( zd>m7^F{>sV>Q(x^j8M+&9@~I0Utx?4v&{(b=(Sdo7`t4&i_ppXGF;Z1^u|Vz>pJBu zWOj;W6Q}}f4y?(Cb+t08zXo}!E>)=^vWEc{egWC(`v#?$11-oV+Zr)VCTV1CTERA+iRd0LF%zYqtcS%j zZ?#AO&gdfNb$%}@F01P)V4p8aNJbRw1mDg8PN&X_k_+v#pJnrDZCd9T2c4;U^^;Np zf-t>PpgSb~MVp(};nNe)!Gcn6W`dLB<&8oa8Fc4twuI9MHKI&hfYzU2XF1jSXLC#f zy%uhsVxc#C+?c|YV9okq%3HO^WJGmqL8!Zjl(3oR)-+wj>*pyB1(VpBc@+ zF9szW?fPw_AD+759x5GVvjNrWokbd^3KUX^207uWw4;3^T4}9@uNXi|Td-7mj87Ws zT39&o`zM;#7X^qGyv6eQo;tIH`T-gooaI`Gc5o?n>Y0+gCxsC1idGv_z#0bYQ%K@F z#6PF}j8GGdN;;yE;~S^OIg;Xtqf8SS@CBVCom4EQGe;!9La1m4yLThIUT=s%b`MrE zZsRQIN^0}siAk4FlVLt3{o;9Hl2({*7;5yaLlCz@`1F2!%>08{ssTATy=w=5PuZ(` zTx0SJySN`JYl7g~YcKLI)HVv!#^mN^TFI@NB#^zt9$?+tXIPhjrjVR0d`hSu=*QfG z8^+k&7>|<#E&o&U0y-w~g0@Qp)nU+~nhO`^3YT715Liwq4(Q%B*ls(8g}ujkQDC}Y zWUrCyfpJ)+MY?kp_@XnOkO-V@)QH;CrT58iZH9^2XHDP`gpnHi-PK?0us@j7o3Zs{ z;aF#55(lcS^?otGVmJZ1O49sC7OAn7z2xR3wq*~|M4->Xb)L;( zEO6P9xM#y^KI*l6))Z&0;F_eMAS7tN7V58GUBXl-8f)Il-BW%#9ex@bWfj7DQutbZ zgOk#sm?)_L&xq2ddEyKR!4R#A><2lO<@jj&c>&aSkDPKy2NYHts_|6IHj*F67o^Zz zqM_ci!;cN>hR^@dkJtpj=$UKEO59~^Q8U39*RTpqTzH0|@g-oy|3B0S*00GTcnp~D zlQsS{w&Tq?gz}}}Dg^JY69B~l0q>NjMS;FwrIE~zC6dvbkDiojdg4xv((6^so4?Jw z>xU!9t!mOmBLV7e!V0`YFxGpI}K-tMJ@G z#6w~W-feM0h2B0r=GH$^bHqJXhqEj8T0eRFWLPQ$QT<*s3*uiy@E)`B_RcSt;L&*_hzK*c3d4`$CEu3rc1H(Lh#Vg{fEPd`5} za4E3=YQP~3!d92M*K>U>ByK5a zxCPQhgRMlWLDOs3-Sd7DjBPjN)a#mv5zXM=T{ia~(=&sW&rPkQ%gZTWv6j@771Q#; z1vt>uV~hW$I21E)eflBkNSVoExvcOUf#Sb^F>+q>{aH*UuHxFegci~Scu9AsebZ>x zeZELPqK9cqGcJy9GAxh>_`dLmvxh2!+Tg&LQ*stu zX;zU<_!&ZU4GtrbIWLoMl?nTKvM1dn!t6c>857kubZQR7%q#aX85GSW>Zw?Tbwh{Y zr^lr%)*&&*aPCdaS1ItX?DxhsmjA9u7DMYXZVVedwQu4(tDv`)SY>Xe9IvhW50DmF zEQ(pBnIOEm(ojB8XKf@t+<$WYS@?JF(pQ3xb_qkV6x13oHLYIQ(RN3*mD7VX-42A)xb#3GZfXephim@b2zn1GCGTy8oRXe&H3q zacR5`a1EyCR-HIvvGQdFt0K*zhgK#F>)$ZR)K`!7mx!$~gLsQ+3Z^p!pGIBcuephz zY6pkc=kNvW^}U*Zk+AX#Z!%}5{NfpAw7fl=2YUlIzq%~~Pji%0jCi{#codtw)Ng6l zaDhkvJ6e(*a@Vm1&4yVj{L%4HE5Mk+?aCU6NQchWQ~N0kQ@{Wa=QMnoFv<0lg`YCX zFi~kxA|wn|BuCq>pfT1WQKvZLbU|99`Cuh(!6)IRPC`qrAuYm+iIL$mwGv#W6cW24(dJ034AB=e8Nfh}&ndIyeR#o*~sQ1VS@Ac-S5f+_OqN0bI z8p|8^9^30c?ACvqgmkY#Dt-L)aej;)M=K$z%jwOOXXo#GPR(6F()&J|eLQ8q3&ndu z`qckB=J+QvIMxg>%*(FI(eWKi5ygtj$wzT9SM4SBiC*tVwFFh%O8XBZ-FLA(3=!0n z3fH>edOouds{)`nJP0EqTGX#wQ}~JsO4l_|^K&e$I?s*Zw0zg3R_*o;Q+=R&@Qf^0 zLW1Fs6mg7Yf5&8Sde&1@G7SjG!SV5pm> zFv)INMOiNf?@9;n98&sYxFpm{w5xW|cPb#nd5jWyx(0eOl!|1aD@@{3(`(wjcv2Lc z!CP7#w=%B!R6l>qRlK9iRO2GzCF!Eg7eIhuwn1R$y0((77v&yK+9`PS(wa?1N=DmpF26qj zJa6vpl8#3`Ce>5*+u6)@U%;gQ7nk-R>xdlR=?gAVYibm|j?s{IN7BS32l3kuWtN_O zT$b7Q%r4foM=LpIiregTlN%6l{K1w%ykA?Y6vs`Do1)}-9#0)kkCjCRYbrt}PFkq9 zU0MdwEhYo@Ves9^_L-kM@aS{G;F>480_z0;3oJN3ZNO%>m(Hk8-TRc=FG%(8BwAJW zL>1p7K3D|ai)qITogMTQqTPqq2?ppN>aOD^p8x))>e~%zKIy>+dt10GU4Q$&SqDDy zbb73&&gpnS-L);I_d=KVx^PSd1V<-mg~<#QWE3?$;}$#AG_*k|K^G#6y3FDD1eVM)n5Xe}RWPn9PFJv%zcGW%_KYXzA zxcnhEUhzEOnB!A|5a-)UIu--4ThGDor3x3&1-c4!`k=WPb4pE1fLFQ}xd=3O&K0Q7p2aIe_*x+lzBLCk=M&w@>tVvF@3wWib?7sJG p`C-JJ%0j`I&nJ{EuQ6W|Q~!VSuFAa-1~GHUPxj^DK>xS!e*o1tuF3!a literal 0 HcmV?d00001 From 7bbe19694ba0c28d5c70422e4da610d82193a3aa Mon Sep 17 00:00:00 2001 From: dzhou6 <60240968+dzhou6@users.noreply.github.com> Date: Sat, 26 Oct 2024 16:33:12 -0400 Subject: [PATCH 2/3] Update Recipio.py Removed exposed API Key --- backend/Recipio.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/Recipio.py b/backend/Recipio.py index d4a2eb1..3c80574 100644 --- a/backend/Recipio.py +++ b/backend/Recipio.py @@ -23,7 +23,7 @@ from IPython.display import Markdown #api key -GOOGLE_API_KEY="AIzaSyDVzXO4sbVSVPDSccjiy4Mz3NDtWIDkwVU" +GOOGLE_API_KEY="YOUR_API_KEY_HERE" genai.configure(api_key=GOOGLE_API_KEY) from PIL import Image @@ -95,4 +95,4 @@ def preload(): hold.append(x) hold.append(input("Enter measurement for "+x+" (include units): ")) return hold - #store(input_image) \ No newline at end of file + #store(input_image) From 07e415ba68fa5de59256544b1838e50c7d50fa28 Mon Sep 17 00:00:00 2001 From: David Zhou Date: Mon, 4 Nov 2024 16:09:20 -0500 Subject: [PATCH 3/3] -Fixed Prompt --- backend/Recipio.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/backend/Recipio.py b/backend/Recipio.py index d4a2eb1..f98a86b 100644 --- a/backend/Recipio.py +++ b/backend/Recipio.py @@ -23,7 +23,7 @@ from IPython.display import Markdown #api key -GOOGLE_API_KEY="AIzaSyDVzXO4sbVSVPDSccjiy4Mz3NDtWIDkwVU" +GOOGLE_API_KEY="YOUR_API_KEY_HERE" genai.configure(api_key=GOOGLE_API_KEY) from PIL import Image @@ -35,7 +35,7 @@ def to_markdown(text): #this is the function that we're gonna use to run the image recognition thing def imager(image): model = genai.GenerativeModel('gemini-1.5-flash') - response = model.generate_content(["Generate a list of the ingredients provided in the following image using * as bulletpoints", image], stream=False) + response = model.generate_content(["Generate a list of the ingredients provided in the following image using * as bulletpoints and be specific about what the ingredients are and do not include duplicates", image], stream=False) to_markdown(response.text) print(response.text) return userinput(response) @@ -84,7 +84,7 @@ def process_image(image): blob.download_to_filename('spices.jpeg') ''' def preload(): - image_path = "backend\\spices.jpeg" + image_path = "spices.jpeg" input_image = Image.open(image_path) #input_image=Image.open(sys.stdin) process_image(input_image) @@ -95,4 +95,6 @@ def preload(): hold.append(x) hold.append(input("Enter measurement for "+x+" (include units): ")) return hold - #store(input_image) \ No newline at end of file + #store(input_image) +#testing the function +preload() \ No newline at end of file