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 6612947c0..81593896c 100644 Binary files a/webpages/__pycache__/SendEmail.cpython-312.pyc and b/webpages/__pycache__/SendEmail.cpython-312.pyc differ diff --git a/webpages/__pycache__/__init__.cpython-312.pyc b/webpages/__pycache__/__init__.cpython-312.pyc index 7cfdb92f0..cca1ee879 100644 Binary files a/webpages/__pycache__/__init__.cpython-312.pyc and b/webpages/__pycache__/__init__.cpython-312.pyc differ diff --git a/webpages/__pycache__/buff_bot.cpython-312.pyc b/webpages/__pycache__/buff_bot.cpython-312.pyc index 3fd081645..fd86a6935 100644 Binary files a/webpages/__pycache__/buff_bot.cpython-312.pyc and b/webpages/__pycache__/buff_bot.cpython-312.pyc differ diff --git a/webpages/__pycache__/classroom.cpython-312.pyc b/webpages/__pycache__/classroom.cpython-312.pyc index 05ed621a5..7f8856bb1 100644 Binary files a/webpages/__pycache__/classroom.cpython-312.pyc and b/webpages/__pycache__/classroom.cpython-312.pyc differ diff --git a/webpages/__pycache__/code_editor.cpython-312.pyc b/webpages/__pycache__/code_editor.cpython-312.pyc index f292b06ea..5d3d7d243 100644 Binary files a/webpages/__pycache__/code_editor.cpython-312.pyc and b/webpages/__pycache__/code_editor.cpython-312.pyc differ diff --git a/webpages/__pycache__/event.cpython-312.pyc b/webpages/__pycache__/event.cpython-312.pyc index 71003724d..0b8a55394 100644 Binary files a/webpages/__pycache__/event.cpython-312.pyc and b/webpages/__pycache__/event.cpython-312.pyc differ diff --git a/webpages/__pycache__/home.cpython-312.pyc b/webpages/__pycache__/home.cpython-312.pyc index 46871ba87..6c599dd4e 100644 Binary files a/webpages/__pycache__/home.cpython-312.pyc and b/webpages/__pycache__/home.cpython-312.pyc differ diff --git a/webpages/__pycache__/join_us.cpython-312.pyc b/webpages/__pycache__/join_us.cpython-312.pyc index 75a021884..2c8dd71b8 100644 Binary files a/webpages/__pycache__/join_us.cpython-312.pyc and b/webpages/__pycache__/join_us.cpython-312.pyc differ diff --git a/webpages/__pycache__/navigation.cpython-312.pyc b/webpages/__pycache__/navigation.cpython-312.pyc index 8ce0a1b29..8252995de 100644 Binary files a/webpages/__pycache__/navigation.cpython-312.pyc and b/webpages/__pycache__/navigation.cpython-312.pyc differ diff --git a/webpages/__pycache__/outstanding_members.cpython-312.pyc b/webpages/__pycache__/outstanding_members.cpython-312.pyc index 9dd459cb8..f714f1ee5 100644 Binary files a/webpages/__pycache__/outstanding_members.cpython-312.pyc and b/webpages/__pycache__/outstanding_members.cpython-312.pyc differ diff --git a/webpages/__pycache__/project.cpython-312.pyc b/webpages/__pycache__/project.cpython-312.pyc index ca90e2655..c4ae24010 100644 Binary files a/webpages/__pycache__/project.cpython-312.pyc and b/webpages/__pycache__/project.cpython-312.pyc differ diff --git a/webpages/__pycache__/reference.cpython-312.pyc b/webpages/__pycache__/reference.cpython-312.pyc index b9a355750..414db5c79 100644 Binary files a/webpages/__pycache__/reference.cpython-312.pyc and b/webpages/__pycache__/reference.cpython-312.pyc differ diff --git a/webpages/__pycache__/testing.cpython-312.pyc b/webpages/__pycache__/testing.cpython-312.pyc index dcecc6259..3a249e3c0 100644 Binary files a/webpages/__pycache__/testing.cpython-312.pyc and b/webpages/__pycache__/testing.cpython-312.pyc differ 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 303253ed9..1f62b97c2 100644 Binary files a/webpages/bufftools_pages/__pycache__/letter_generator.cpython-312.pyc and b/webpages/bufftools_pages/__pycache__/letter_generator.cpython-312.pyc differ 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 6af447745..483d219db 100644 Binary files a/webpages/cis_tech_challenge_pages/__pycache__/cis_tech_challenge_homepage.cpython-312.pyc and b/webpages/cis_tech_challenge_pages/__pycache__/cis_tech_challenge_homepage.cpython-312.pyc differ diff --git a/webpages/coreteks_pages/__pycache__/coreteks_homepage.cpython-312.pyc b/webpages/coreteks_pages/__pycache__/coreteks_homepage.cpython-312.pyc index cfd1a0813..ff6cd1c12 100644 Binary files a/webpages/coreteks_pages/__pycache__/coreteks_homepage.cpython-312.pyc and b/webpages/coreteks_pages/__pycache__/coreteks_homepage.cpython-312.pyc differ 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 c08307a99..dbe386648 100644 Binary files a/webpages/pythonx_lessons_pages/__pycache__/pythonx_finance.cpython-312.pyc and b/webpages/pythonx_lessons_pages/__pycache__/pythonx_finance.cpython-312.pyc differ 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 354321452..b69b3951a 100644 Binary files a/webpages/pythonx_lessons_pages/__pycache__/pythonx_geomap.cpython-312.pyc and b/webpages/pythonx_lessons_pages/__pycache__/pythonx_geomap.cpython-312.pyc differ diff --git a/webpages/pythonx_lessons_pages/__pycache__/pythonx_homepage.cpython-312.pyc b/webpages/pythonx_lessons_pages/__pycache__/pythonx_homepage.cpython-312.pyc index f6894034b..07a2d5286 100644 Binary files a/webpages/pythonx_lessons_pages/__pycache__/pythonx_homepage.cpython-312.pyc and b/webpages/pythonx_lessons_pages/__pycache__/pythonx_homepage.cpython-312.pyc differ diff --git a/webpages/pythonx_lessons_pages/__pycache__/pythonx_introduction.cpython-312.pyc b/webpages/pythonx_lessons_pages/__pycache__/pythonx_introduction.cpython-312.pyc index c1b7db8a1..33e0416c4 100644 Binary files a/webpages/pythonx_lessons_pages/__pycache__/pythonx_introduction.cpython-312.pyc and b/webpages/pythonx_lessons_pages/__pycache__/pythonx_introduction.cpython-312.pyc differ diff --git a/webpages/pythonx_lessons_pages/__pycache__/pythonx_wordcloud.cpython-312.pyc b/webpages/pythonx_lessons_pages/__pycache__/pythonx_wordcloud.cpython-312.pyc index 895858fa2..99b0cf7e9 100644 Binary files a/webpages/pythonx_lessons_pages/__pycache__/pythonx_wordcloud.cpython-312.pyc and b/webpages/pythonx_lessons_pages/__pycache__/pythonx_wordcloud.cpython-312.pyc differ diff --git a/webpages/requirements.txt b/webpages/requirements.txt deleted file mode 100644 index 7e42b57b4..000000000 --- a/webpages/requirements.txt +++ /dev/null @@ -1,13 +0,0 @@ -folium==0.19.5 -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 -wordcloud==1.9.4 -yfinance>=0.2.59 \ No newline at end of file