From edd3dca1be32590acb303543b786881e603abf7a Mon Sep 17 00:00:00 2001 From: Carl Zhang Date: Tue, 30 Sep 2025 15:30:31 -0500 Subject: [PATCH] add a page for AI image Editor --- .gitignore | 4 +- app.py | 3 + app_config.json | 12 +-- requirements.txt | 89 +++++++++++++++--- webpages/__init__.py | 5 +- .../__pycache__/SendEmail.cpython-312.pyc | Bin 4363 -> 4378 bytes webpages/__pycache__/__init__.cpython-312.pyc | Bin 1149 -> 1243 bytes webpages/__pycache__/buff_bot.cpython-312.pyc | Bin 6393 -> 6348 bytes .../__pycache__/classroom.cpython-312.pyc | Bin 856 -> 878 bytes .../__pycache__/code_editor.cpython-312.pyc | Bin 2351 -> 2352 bytes webpages/__pycache__/event.cpython-312.pyc | Bin 428 -> 450 bytes webpages/__pycache__/home.cpython-312.pyc | Bin 4903 -> 4925 bytes webpages/__pycache__/join_us.cpython-312.pyc | Bin 6196 -> 6181 bytes .../__pycache__/navigation.cpython-312.pyc | Bin 2472 -> 2579 bytes .../outstanding_members.cpython-312.pyc | Bin 5194 -> 5162 bytes webpages/__pycache__/project.cpython-312.pyc | Bin 3284 -> 3291 bytes .../__pycache__/reference.cpython-312.pyc | Bin 1106 -> 1128 bytes webpages/__pycache__/testing.cpython-312.pyc | Bin 401 -> 423 bytes webpages/buff_bot.py | 2 +- .../letter_generator.cpython-312.pyc | Bin 11061 -> 10959 bytes webpages/bufftools_pages/ai_image_editor.py | 60 ++++++++++++ ...is_tech_challenge_homepage.cpython-312.pyc | Bin 6400 -> 6422 bytes .../coreteks_homepage.cpython-312.pyc | Bin 9284 -> 9259 bytes webpages/navigation.py | 1 + .../pythonx_finance.cpython-312.pyc | Bin 7124 -> 7146 bytes .../pythonx_geomap.cpython-312.pyc | Bin 7806 -> 7800 bytes .../pythonx_homepage.cpython-312.pyc | Bin 2790 -> 2812 bytes .../pythonx_introduction.cpython-312.pyc | Bin 22668 -> 22690 bytes .../pythonx_wordcloud.cpython-312.pyc | Bin 4084 -> 4106 bytes webpages/requirements.txt | 13 --- 30 files changed, 156 insertions(+), 33 deletions(-) create mode 100644 webpages/bufftools_pages/ai_image_editor.py delete mode 100644 webpages/requirements.txt diff --git a/.gitignore b/.gitignore index 7b5ebd350..e155a8b0f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ new_members.json -files/student_locations.db \ No newline at end of file +files/student_locations.db +venv/ +__pycache__/ \ No newline at end of file diff --git a/app.py b/app.py index 83c0e4e70..b446f030e 100644 --- a/app.py +++ b/app.py @@ -20,6 +20,9 @@ elif page_label == "BuffBot": elif page_label == "Letter Generator": pg.letter_generator() + +elif page_label == "AI Image Editor": + pg.ai_image_editor() elif page_label == "Outstanding Members": pg.outstanding_members() diff --git a/app_config.json b/app_config.json index 61e2a3213..c06a962c9 100644 --- a/app_config.json +++ b/app_config.json @@ -5,6 +5,12 @@ "model": "gemini-2.0-flash" }, + "nano-banana":{ + "api_url": "https://generativelanguage.googleapis.com/v1beta/openai/", + "api_key": "AIzaSyCiURTUJrEGw5J7HxtL1KRNT9GhNKCJsb0", + "model": "gemini-2.5-flash-image-preview" + }, + "deepseek-chat":{ "api_url": "https://api.deepseek.com", "api_key": "sk-12165b127043441697a8940918e207ac", @@ -23,12 +29,6 @@ "model":"deepseek-r1:1.5b" }, - "grok-3":{ - "api_url": "https://api.x.ai/v1", - "api_key": "xai-Zr3drSBcFVBew5Y6KwzEmIA9pUoOxpSpSRoMoJ5vZo4kFMKHqJnTdll8wY3Q5U4aVUhSgHRZWmUXJc1D", - "model":"grok-3-beta" - }, - "send_email": { "sender_email": "noreply@buffteks.org", "password": "cidm4360fall2024@*" diff --git a/requirements.txt b/requirements.txt index 9e7c40771..2d5b49e76 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,13 +1,80 @@ -folium==0.19.5 +altair==5.5.0 +annotated-types==0.7.0 +anyio==4.11.0 +attrs==25.3.0 +beautifulsoup4==4.14.2 +blinker==1.9.0 +branca==0.8.1 +cachetools==6.2.0 +certifi==2025.8.3 +cffi==2.0.0 +charset-normalizer==3.4.3 +click==8.3.0 +colorama==0.4.6 +contourpy==1.3.3 +curl_cffi==0.13.0 +cycler==0.12.1 +distro==1.9.0 +folium==0.20.0 +fonttools==4.60.1 +frozendict==2.4.6 +geographiclib==2.1 geopy==2.4.1 -matplotlib>=3.10.1 -openai==1.75.0 -pandas==2.2.3 -plotly==6.0.1 -python_docx==1.1.2 -streamlit==1.44.1 -streamlit_ace==0.1.1 -streamlit_antd_components==0.3.2 -streamlit_folium==0.25.0 +gitdb==4.0.12 +GitPython==3.1.45 +h11==0.16.0 +httpcore==1.0.9 +httpx==0.28.1 +idna==3.10 +Jinja2==3.1.6 +jiter==0.11.0 +jsonschema==4.25.1 +jsonschema-specifications==2025.9.1 +kiwisolver==1.4.9 +lxml==6.0.2 +MarkupSafe==3.0.3 +matplotlib==3.10.6 +multitasking==0.0.12 +narwhals==2.6.0 +numpy==2.3.3 +openai==2.0.0 +packaging==25.0 +pandas==2.3.3 +peewee==3.18.2 +pillow==11.3.0 +platformdirs==4.4.0 +plotly==6.3.0 +protobuf==6.32.1 +pyarrow==21.0.0 +pycparser==2.23 +pydantic==2.11.9 +pydantic_core==2.33.2 +pydeck==0.9.1 +pyparsing==3.2.5 +python-dateutil==2.9.0.post0 +python-docx==1.2.0 +pytz==2025.2 +referencing==0.36.2 +requests==2.32.5 +rpds-py==0.27.1 +six==1.17.0 +smmap==5.0.2 +sniffio==1.3.1 +soupsieve==2.8 +streamlit==1.50.0 +streamlit-ace==0.1.1 +streamlit-antd-components==0.3.2 +streamlit-folium==0.25.2 +tenacity==9.1.2 +toml==0.10.2 +tornado==6.5.2 +tqdm==4.67.1 +typing-inspection==0.4.1 +typing_extensions==4.15.0 +tzdata==2025.2 +urllib3==2.5.0 +watchdog==6.0.0 +websockets==15.0.1 wordcloud==1.9.4 -yfinance>=0.2.59 +xyzservices==2025.4.0 +yfinance==0.2.66 diff --git a/webpages/__init__.py b/webpages/__init__.py index 63d9bdf67..4c0ea71af 100644 --- a/webpages/__init__.py +++ b/webpages/__init__.py @@ -8,11 +8,14 @@ from .reference import reference from .pythonx_lessons_pages.pythonx_homepage import pythonx_homepage from .pythonx_lessons_pages.pythonx_introduction import pythonx_introduction from .buff_bot import buffbot + from .bufftools_pages.letter_generator import letter_generator +from .bufftools_pages.ai_image_editor import ai_image_editor + from .pythonx_lessons_pages.pythonx_finance import pythonx_finance from .pythonx_lessons_pages.pythonx_geomap import pythonx_geomap from .pythonx_lessons_pages.pythonx_wordcloud import pythonx_wordcloud from .outstanding_members import outstanding_members from .cis_tech_challenge_pages.cis_tech_challenge_homepage import cis_tech_challenge_homepage from .coreteks_pages.coreteks_homepage import coreteks_homepage -from .SendEmail import send_email \ No newline at end of file +from .SendEmail import send_email diff --git a/webpages/__pycache__/SendEmail.cpython-312.pyc b/webpages/__pycache__/SendEmail.cpython-312.pyc index 6612947c0c36ac7b3d3be66350e0630525c73baa..81593896c94398ff748bf6c900f5864856d43d1f 100644 GIT binary patch delta 134 zcmeBHnx({dnwOW00SF@Rtw|RW+Q?_jZ|&x66%$&VT2vg9T$PcSmmcGiTAW>yUl8L| znwA!lnq3TMgr_DIXO^VKl&2;YB&Mep$4pM+S7JOhxsyMU`3kT3`16aq@irM2^e6<{ucCIW;FU3us9I=`UOioO~DfG_G=Je&+`A QA(GAl%NT!6ekEW404ZW4qW}N^ diff --git a/webpages/__pycache__/__init__.cpython-312.pyc b/webpages/__pycache__/__init__.cpython-312.pyc index 7cfdb92f0bae9f172d938f25dea6a81d2508e4ed..cca1ee8793ef71fcca119cc45a3605d00decbe76 100644 GIT binary patch delta 333 zcmey%ahsF(G%qg~0}$A0-^n;Tkyn!O#YFWj++tB;j0`CZDFQj-6Q9Wm09nF0GP$x* zvWyIsBATL;IT#o4Bxc5E<|d}6#;2xaPF~13gHdj>71ItS`J~dcw37V%oZ|Qbplq=o zvbvJ|q9VS@@0he1`6o*;Yq1FcZN8;GIi5*Qpgg}QB{?U*G^I!oC|D#kxq{h>QF!uZ zX0>_|kSfmL)Vvhe+{DbBB2gfJCBtVR$?(h7*(xTqIJKxaCb=pjF)uyFCAB!aB)=fW z3FwTF)a+t7BRn;!II|=*raUzX?68>l_{_Y_lK6PNg34PQHo5sJr8%i~MJhm38G*Ri x4oG}pW@KcX?8G9c@RY&sE`!Ze2B*6W4tE*c?lPF%Wr)4YV1JK6u}BH15&+s3XMz9# delta 235 zcmcc3`Im$DG%qg~0}!yM%4Sqd`6qWV>#_*|O)CbKBEkk-UO-U+ATCay>?f>mdzDlD4zJ)8jTz1>)UWayZAiSs z!`JWL={~`6y4ysz$sP+TuJRasXJ+6t1`=EvU)UH}+1tGuy;^)8iNsGnA{@(ng;Qa( zrbsxW3j>$pmk34%K9L#jD{`*zS~s`>Rdez5%XiApkX{jXjnm`~2UkCLC-(&ruPYqh zAoEPWa4?97T^ClqD6D*4Sm%oHcAr_9m82f3+AU!Gz|5egzMyPjeBB%PV?*WWJ&tK$J z`1L&w$TGdiY4Yp45YWLFd2N1u7Xdo#qM-SoPeMS8zjFdjz96ax(kx_qLC|LMSMiOS n2B0Y91rea=DFUUaB5n}D10-&7*yQG?l;)(`75Pp+FQEkh>%7V* delta 675 zcmX9+K}-`t6rHizvfJ%I+ud$~0tMPi(ZaG|^k4&tCTIYag8?A{1G+$^wYUYnYBVvN zfQ$(>##l^Ddhj6W1&>~g3C2je36b<*JbTz;o!sE?wIt9XKk>OPRDP-@`bg9h3o2ac2b?sCRbJYfjYl3x2R_2ViM2rLB{ed zs_Eq2WKVx@U(Z5nF1uto7q!fC&j9`A-efdCAQ$hEZj2l0i~7enKtl~XSfU>q3b=*d z@#LLhxS>Uh9le0`Z@|n70$+N6r;3lU`Xp!f7o=qe7o+6rvv3**Em2AUBn` zt_nKAC}rY(7Ry~Mbm^quK$uhLOQBH$Z#p1bbt0zj>ByszCu2XvB;6Ng*b>)npl&8o zJS|S*aX3_OU{o*WE)`NbIsb4NN?h)Z(0V8rEKKO!nF_+p7%sD}4St>fDvs#vsOhjn zRThcTp%6Y0!iPfqK!_hBCqqB_W2{aRP{qY*#V-)>_FQp;cQSF>Af<R`5NZI4t z=C}CVuz>&w^z3(27+PuBNSJj$;t0V#{Tjv)E?+Uk=Ok0i_yA%M@Ys8lk_( zK4@%m(8sVR1t>r_Y!>uWV7FVbADr06eoW2&d>U^XHyDdeq%*hIQtF^~mA-B~^$!aM B#f<;} diff --git a/webpages/__pycache__/classroom.cpython-312.pyc b/webpages/__pycache__/classroom.cpython-312.pyc index 05ed621a55670a9455e8d807964d7b170d5de2d4..7f8856bb13a775f03fe414d04fce3e22f105c376 100644 GIT binary patch delta 92 zcmcb?_KuDBG%qg~0}w>sTazBYkvE9R+RfQ2CbT%Us5mCMDkCv3J;o)qIJ+djAjYXQ nEiEK9yBN+0PfaS$EJ=+iPfaRFOiwM2ncTv(lJVALJ!UNc$i^X4 delta 70 zcmaFIc7u)gG%qg~0}!yM%4P&_NK8*H)}K6!X(i*Y$u7)V0NlD3!TsTa$ikBd@FG% zToN5}AB`AzgzpH7UJx_bpnOHpY=`0v0m13)6WM35UlCCF&deZWKDnR0j2Eon$ZO81YNVf$pPQ9G;p~oLQ2p zU!Iy&keHrYtiQRQaUQFP9U}un1H&Co?tYn0nQpm{40^1hlXci#41n|p5a**21CQ_> zLD36h1{;(w3z~gkVB}TYp?E_;a60=$_8II~1QfnA1BE8fU@sGbY5Hyg6alN8EX|?G R0TZ6=$+4dC*W{lZ<^X!XH2wep diff --git a/webpages/__pycache__/event.cpython-312.pyc b/webpages/__pycache__/event.cpython-312.pyc index 71003724dfa17f6e6337d35a84a5aa63d9b3a94c..0b8a55394727126fcdb2fa5559c6a90248996c92 100644 GIT binary patch delta 91 zcmZ3(e2AI%G%qg~0}w>sTa#Wek@t Xo|;sUn4Vg!KiPyah4I(qnT(nM)RGpI diff --git a/webpages/__pycache__/home.cpython-312.pyc b/webpages/__pycache__/home.cpython-312.pyc index 46871ba87e7a9136ca3192144b7858bc03ed4a7c..6c599dd4eb9d1b47d3b390b20b630307c9771957 100644 GIT binary patch delta 92 zcmZ3kwpWe!G%qg~0}w>sTa!L>Bkx~9Ye#3Rn9$|!`0JT<8}vm`a9JT<8xF+H_7X0pD}DaKoqe+lUV00C4Y+5i9m delta 70 zcmdn1wp@+(G%qg~0}!yM%4P^`9G;p~oLQ2p YU!Iy&keHrYtUuXR=oI6x$pXT<0Oq_F%>V!Z diff --git a/webpages/__pycache__/join_us.cpython-312.pyc b/webpages/__pycache__/join_us.cpython-312.pyc index 75a0218843bb035e041c437f6ba37ac3bcd9b961..2c8dd71b80a8835d9f658e5922ce8f1fb7a0018d 100644 GIT binary patch delta 274 zcmdmDu+)I}G%qg~0}w>sTa$ivBdM#2pi+A&32q|OpH4x&*e5^z9OhU`8v0S z4TF%u7ZCz(qbwNV^DzCxhP##BS20p{dGkJ`dmT^wL%%jH4pr|$ZFOQrI(A4m4Z!BCiUVVR(_(U~?^R M7#HKM$ydY^0D`ky-v9sr delta 269 zcmZ2#u*HD)G%qg~0}!yM%4Vc(NK8*H*5BOEbcBuZ*X9t;I3~t>lQ(l4aab)YcTl*w}mi}{vyJ_Cv-tb z`7*D{2L>iigUNb4GU7n`3l{^QKz~$c)CCFs%e)338Q3|cCdcqNGK1&^JVqRgIX?l_ zyD?6_!lT9lX8h%m;{clY5p297udw@NLA?(QjJ%c`RPG3fOy``)Imdd2?h26&iB|a~6WH3#dAwmJXwVAG%qg~0}x!$x|6}rIgu}fF=S)1EaT)IjPioKDST_#Rx^R585q);*6>eG zU{;@eoiTdyIz~-qu@v#i0!;GE5-E~kzEp}dm@fn5pJVC+nJ~GXnU9$jqEApYMGeU` zW{4=WdWr@}m!M{f7LqI@M3z;1jm~PuNsOw(x+!`{(p)L}YYZlbu~;%1PM*NBTds=V z(Nn=QH!(d`!8IkbB)_PNJ1J8kDN{ESB(~X`^#!A~yR%hHXmM&$aZGYmMq*xij7w^9 zc1eCgj8kb^T1aYkF`N;enpB)wk{VN`S}-iFvK0?r>;neF(#FfjA-f8p5tft{Vv(UDO}p6i1PBZH{q z7gt6lF{uu&@9Yd*A|L!18F<7lu!w&5XGG@yD&_$O_GAwR4_W3DvaBBJlg&9@7;jCk P;Z)(!W)v$@1Ihvb#C3TU delta 355 zcmbO%vO<{eG%qg~0}!yM%4W>qn8+8xsIf6wmXRf$aSiX}4UFo{d@1~s8<;dFUuTS- z+`uT$ES4e;;xkL6NP_uNP`-4E3|QTFrc{=6R*2@w)y#a%%us_=Q`A5j1l3bC*08N+ z0$Iwy0JDZwbB)$&#>omSYCx@+_%H?deU>QCOovU~GX))$PbhWZ)#xvBce ziA6d3PNivSA*tEL;i*Z*nI)LY^+>*NpY{yZO;ne6z!Ffj4*e_`7k#lg<#V6Q08^}&geK~(aKGozxIR0r30b`@5s z4?c_xJYpAEM8EqoB6EKg^8h_C*HK6f05#$^rl) Ce_#jz diff --git a/webpages/__pycache__/outstanding_members.cpython-312.pyc b/webpages/__pycache__/outstanding_members.cpython-312.pyc index 9dd459cb8cabb56bb416e05f5c88a1da4dfa5f2e..f714f1ee53d13a1f2fde2c51ff7355d1aa83b81c 100644 GIT binary patch delta 276 zcmX@5u}XvYG%qg~0}%MA+{t*qk+(?DI>6Z~CbT%Us5mCMDkCv3J;o)qIJ+djAjYXQ zEiEK9yBN+0PfaS$EJ=+iPfaRFOiwM2nY={MlyUatTY^SXw>U-aaB%f=baGq})Y@Qt zmBZpYGXt0CBTmuD211%Zrr6{dAyc3-LAWx#4aHYEY(UC{9&rjy-U?PGJozD-GOZ2D zS2@h#%B+N?9T>QTzi=_IvbTFTdVgSG66E;Gz{JY=J)99}W2f}5=bWOQGQYmd01fVx c0P=)7B!7KZ0rEPayvb{Yiy3cCRus_$0B*)vh5!Hn delta 313 zcmZ3baY}>tG%qg~0}!yM%4Y1`$Xg_+YNel%pPQ9G;p~oLQ2p zU!Iy&keHrYtUq~|pef_U$sYubRBmvJd}Lr`wYx*PyjQ z`6`DwNP`7f0~4zjNRG3UbAsL#4n+`~r<3P`sKylz&F`#0*~tOIV)j7yfF1hlI}6Y$ uU~7JTmjPM|b`3=I1IV?%zN-LD{s45N1yB^I{R0EYj9%el#$S^eMKl2peO~MU diff --git a/webpages/__pycache__/project.cpython-312.pyc b/webpages/__pycache__/project.cpython-312.pyc index ca90e26552c684d9cdf39a27170bacdb30d225f9..c4ae2401020cc598648fe2b8baa253ba846f5f61 100644 GIT binary patch delta 171 zcmca2d0Ue2G%qg~0}w>rTa(Vnxsh)lm$i$tRZM7cYEf}aa#coRUV4m6YH@Z+enE^= zXg<4I(^ JHF*V(4gfz=Hv#|v delta 164 zcmcaDc}0@%G%qg~0}!yM%4VG4*vPk!OI1%lBR@A)KRK}|N8hP5EiEK9yEr^GsW`JF zRlhtnsUR^uwOD^LJGU&O>10*zSgRYHf*%-aP@O^a$FEJyuxAhof#LUXis~|{@yOa9^1FNXO7Y0^N!SBpK(aD>*dxb&jK-zzOX9Eg-0I8nr%ah3XYw~&? F9RRW&FM9w0 diff --git a/webpages/__pycache__/reference.cpython-312.pyc b/webpages/__pycache__/reference.cpython-312.pyc index b9a3557507e78df4d90d3270bb0a7ca46256ce8c..414db5c795fec6160e631926f238ccae8bc12235 100644 GIT binary patch delta 92 zcmcb_@q&Z*G%qg~0}w>rTazxkk++T6+RfQ2CbT%Us5mCMDkCv3J;o)qIJ+djAjYXQ nEiEK9yBN+0PfaS$EJ=+iPfaRFOiwM2nY@F!fbrI3O%_c6!U-WZ delta 70 zcmaFCafyTXG%qg~0}!yM%4YCyNK8*H)}MTixq$K4WP27(0M`;0q5uE@ diff --git a/webpages/__pycache__/testing.cpython-312.pyc b/webpages/__pycache__/testing.cpython-312.pyc index dcecc6259350d79665d60be676d3af1f6899ddff..3a249e3c07787da5fa773c1930eb537873831dd4 100644 GIT binary patch delta 90 zcmbQpyquZ$G%qg~0}w>rTa#Wqk$1nfi?dZsXmM&$aZGYmMq*xij7w^9c1eCgj8kb^ lT1aYkF`N;enpB)wk{VN Xo|;sUn4Vg!Kbf7enDN)-YDOIZy?hn_ diff --git a/webpages/buff_bot.py b/webpages/buff_bot.py index 3ac4378f7..cbbc195d9 100644 --- a/webpages/buff_bot.py +++ b/webpages/buff_bot.py @@ -23,7 +23,7 @@ def buffbot(): st.code(f.read(), language="python") st.divider() # Select AI model for chatbot - model_options = ["gemini-2.0-flash", "grok-3", "deepseek-r1:1.5b", "llama3.2:1b", "deepseek-chat", ] + model_options = ["gemini-2.0-flash", "deepseek-r1:1.5b", "llama3.2:1b", "deepseek-chat", ] # on_change callback to clear chat history when model is changed selected_model = st.selectbox("**👉Please select a model to start**", model_options, on_change=clear_chat) diff --git a/webpages/bufftools_pages/__pycache__/letter_generator.cpython-312.pyc b/webpages/bufftools_pages/__pycache__/letter_generator.cpython-312.pyc index 303253ed9fd4c2562f60ce450b6dd2aa7a1b978e..1f62b97c23af450d6a39c2f82455c76ef025767f 100644 GIT binary patch delta 504 zcmdlQc0QEvG%qg~0}%KNa%RXWZsfbh=pE~96%$&VT2vg9T$PcSmmcGiTAW>yUl8L| znwA!lnq3TMgr_DIXO^VKl&2;YB&Mep$0Pw&l;r2<6vspOnJ7z|y$&XbO z`LA+%+~F0y&Z}{eSK|t=)?|5AS@|o1S}PK72nbGRpU6Ig_qv4sMG5`O5{6dPTUN}8`5ek6xXY*RJ$Z?a6?sXdDxP$$q!W392wMfKCm*# z>3rZ}P*PnkwM1$L>kVa%d(*?R+OmDK1Mh5d0N&U%_G(x2q zqzt|XGBNOJ1Esh;882{peCGiA@1mgAWOhvp9iZNevPQqYvjX*96xIFpT?MG&f~5X0 Yh^7m?TEE~LH`izeGcw+qd_gM}08-ejvH$=8 delta 653 zcmYjO&rj1}82&y=8JjC^fp&DIgt@lsK&)U4hD8r95n~{O2wQN*Wiv%o4B{}xt6sPX zX$&JA9H(^$GjLIE`~x0zlt2@AFov^f>!C?c_8T7jF5mm)ectE&@qC;6obLKc5I*2O zkIXKn2KKs+;nfLgarv1nJjSf z?hMzZwjV+0)X(+2h46m;9oY?;pIrPnFjiVoXKI;h=HvW&a5JI;-pt< z^h#Rq$WdU_#@w9I0YdcJM3Z4ZB(@UemF*jAlcx+Z3}sCmm75sSG%(aic`baogXT7-At2}ze}BW@f8-zdb)Gt9x$XINUz6-B-BY_Y za@YWPa0>4B==?>r-V`i(n{1>US7$YL)BqSg1(k(ZfkMFwp;?`$F?luzQd>qyLOX*)KKbj;Qij?KB{EiLDt$eESS Q|5|k_eiuSVc`_*f1vHDyrT_o{ diff --git a/webpages/bufftools_pages/ai_image_editor.py b/webpages/bufftools_pages/ai_image_editor.py new file mode 100644 index 000000000..c5740f114 --- /dev/null +++ b/webpages/bufftools_pages/ai_image_editor.py @@ -0,0 +1,60 @@ +import streamlit as st +from PIL import Image +from google import genai +import json +from io import BytesIO + + + +def edit_image_with_ai(image, description): + with open('app_config.json') as config_file: + config = json.load(config_file) + api_key = config["nano-banana"]["api_key"] + + client = genai.Client(api_key=api_key) + + prompt = description + + response = client.models.generate_content( + model="gemini-2.5-flash-image-preview", + contents=[prompt, image], + ) + + text_response = None + image_response = None + + for part in response.candidates[0].content.parts: + if part.text is not None: + text_response = part.text + + if part.inline_data is not None: + image_response = Image.open(BytesIO(part.inline_data.data)) + + return text_response, image_response + +def ai_image_editor(): + st.markdown("

AI Image Editor🖼️

", unsafe_allow_html=True) + st.markdown("
Edit and enhance your images with the power of AI! 🎨
", unsafe_allow_html=True) + st.info("Powered by the online [Gemini Image Generation](https://ai.google.dev/gemini-api/docs/image-generation) API!") + # user upload an image and provide a description of the edit they want + uploaded_image = st.file_uploader("Upload an image to edit", type=["png", "jpg", "jpeg"]) + if uploaded_image is not None: + with st.spinner("Loading image..."): + # display the uploaded image + image = Image.open(uploaded_image) + st.image(image, width= 300) + st.success("Image uploaded successfully!") + + edit_description = st.text_area("Describe the edits you want to make to the image") + if st.button("AI Editing"): + if edit_description.strip() == "": + st.error("Please provide a description of the edits you want to make.") + else: + with st.spinner("Editing image..."): + # Call the AI image editing function (to be implemented) + text_response, image_response = edit_image_with_ai(image, edit_description) + if text_response: + st.info(text_response) + if image_response: + st.image(image_response, width=300) + diff --git a/webpages/cis_tech_challenge_pages/__pycache__/cis_tech_challenge_homepage.cpython-312.pyc b/webpages/cis_tech_challenge_pages/__pycache__/cis_tech_challenge_homepage.cpython-312.pyc index 6af4477459665d0c17adc2fa51bdcac381503c44..483d219dbca1d6d55903f45e6f50867a6a9ed6b4 100644 GIT binary patch delta 119 zcmZoLnr6gznwOW00SF@Rtw~oD+sMZ(9#ZIR6%$&VT2vg9T$PcSmmcGiTAW>yUl8L| znwA!lnq3TMgr_DIXO^VKl&2;YB&MeVHDngYm!u|V#3yGY=H#U2rKiS2BsTktH!(8a JntVw@4*--hD}?|6 delta 78 zcmbPc)L_JSnwOW00SMSrWiyV8ZscPYSB=)s$j?pHPfje#(RV6MOAATOE)GvkD$XoP g)h|y?Do9LEE!LmxBQC+Hzd2RBiIMTwm&m}C!+3!+`+G7Y$Tt@`^L~8?`ltZN%134aZOaCVW&QdNbY~)vmGJ93 i&}GR$R?@HUK-o$ls{+gdn}=Xcu25dccx$qhiWUH8xrq1x delta 444 zcmZ4Oam0i7G%qg~0}!yM%4Q^PNK8*H)=$naN-Y6O#6!4~7<80~b%f zbf@$M(Y(u?`4Bl11?+MxKz(%zLE=FA3lCgh=4H;Tj|^-;xyK42;z0U~09-EqGH1d^ z23DY)m!gF@kp994mrK0Nne>qXWad=GU^Fw!FLPEv0R@5zin670WU-?@;OKnH+L`}Lg%=ytG2etj1JIu-2hU*GwV6reIc VfE*9h2D4&vyz)ZEUy~VCv;cU9fyDp- diff --git a/webpages/navigation.py b/webpages/navigation.py index bb35daf81..cbcc2568e 100644 --- a/webpages/navigation.py +++ b/webpages/navigation.py @@ -16,6 +16,7 @@ def navigation_bar(): sac.MenuItem('BuffBot', icon='robot'), sac.MenuItem('BuffTools', icon='boxes', children=[ sac.MenuItem('Letter Generator', icon='bi bi-file-word'), + sac.MenuItem('AI Image Editor', icon='bi bi-image'), ]), sac.MenuItem('Outstanding Members', icon='award'), sac.MenuItem("Join Us", icon='person-add'), diff --git a/webpages/pythonx_lessons_pages/__pycache__/pythonx_finance.cpython-312.pyc b/webpages/pythonx_lessons_pages/__pycache__/pythonx_finance.cpython-312.pyc index c08307a997b712533324abb91a4bf72a81615254..dbe386648d5ee4297a0ce1aab41a6ba9fc75bc8c 100644 GIT binary patch delta 116 zcmca&{>q&1G%qg~0}%KNa%OPKY~;Hp5t!s`6%$&VT2vg9T$PcSmmcGiTAW>yUl8L| znwA!lnq3TMgr_DIXO^VKl&2;YB&Mep#}rhSWaQ^n#OI_I7w6{{$3sLn%S+ZVG2WUy HPudIs7L+Pb delta 78 zcmaE5e#M;cG%qg~0}!yM%4XzAZ{)isq3WZbk)NBYpPX2fqwiFjmKKtlT^yd8RGe9o gs$ZU(RFIgSTC6`=UQ(1%f3vA%9TVfP$y=n&0LDZaR{#J2 diff --git a/webpages/pythonx_lessons_pages/__pycache__/pythonx_geomap.cpython-312.pyc b/webpages/pythonx_lessons_pages/__pycache__/pythonx_geomap.cpython-312.pyc index 3543214529ba914a8f325a3b3341756d55f9a8e9..b69b3951ad069f9313c9751f59cff800f6a9752c 100644 GIT binary patch delta 267 zcmexo^TUSsG%qg~0}%KNa%TMA$or8$Fwxm6CbT%Us5mCMDkCv3J;o)qIJ+djAjYXQ zEiEK9yBN+0PfaS$EJ=+iPfaRFOiwM2DX1*T$j_^Y&q*yV&d)23hlozL6wqeOot!F= z?sb(@{SL3-6pb0qE7Y&@8f{3t!^79_-swKUak|??x5*w0Dz5Svd}n6hGX@e|8ecdV zSlQcs8htJZYF}Z|dBVxvFWxCWLGCK2!e&*$d5j7ST#6Ss6~1!=HC*I1`UTc>kyHKG ycOHn$=GQ_$85wVFek!t&o$>wT=`y*@*Mu}C^T<{(GYD%=ZkJuecx$qjTnGTdz+UkH delta 235 zcmexi^UsF&G%qg~0}!yM%4Vc&9G;p~oLQ2p zU!Iy&keHrYtY1)Bl98WR5ucM@T3r*fP0VAYJk@r}{?*CRW2cyn<6S zW;m}0r! KrTazBSk@o~=V6wASOlWaxQE^OiRYqc7dW=hIadt_5L5x#r zT3SeIb}^h0o|;sgS&|x4o|;sUn4Vf3Q&3rwk)Kx)pOac#oS#=54-uU#z_o_)*5tih FngDmBE3W_m delta 76 zcmew(`b?DfG%qg~0}!yM%4S$?Z_lTpPQ9G;p~oLQ2p fU!Iy&keHrYtUpb8h`P5X{afHhzDq%Y>CRR$p~b01#WBfM8Hsu6F)pda*(Lb} zF;1mvX(6fE#c)P=YEp4#Noq`aYEnUBdTMb@L1jrseqKdb8U{96JxZ%H%?^2L;pngVvZmNEAVo{F1Q)yaSNNRR*cxqB{ uW=X1kd1_KYVtQ(^enDkPMt)vJd`@a{aeiKLJVbP}VX!kR&luF6QvOOJ6$EzT~=0.2.59 \ No newline at end of file