├── .env ├── .gitignore ├── LICENSE ├── README.md ├── __pycache__ └── app.cpython-312.pyc ├── app.py ├── requirements.txt ├── static ├── ai_bot.png ├── css │ ├── image_text.css │ ├── root.css │ └── style.css ├── js │ ├── additional.js │ ├── app.js │ └── image_chat.js └── person_avatar.png ├── templates ├── chats.html ├── image_upload.html └── index.html └── vercel.json /.env: -------------------------------------------------------------------------------- 1 | API_KEY= your api key 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | env -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Yash Kumar Saini 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 | ## Introduction 6 | 7 | Welcome to Gemini-Bot, your intelligent companion designed to revolutionize the way you interact with information. Leveraging the power of the Gemini AI platform, Gemini-Bot provides a seamless and intuitive interface for users to make both text and image queries. Whether you're looking for quick answers, detailed explanations, or visual insights, Gemini-Bot is here to assist you. With its advanced features like session storage and the use of the Fetch API for efficient server communication, Gemini-Bot ensures a smooth and engaging user experience. Get ready to explore a world of information at your fingertips with Gemini-Bot. 8 | 9 | 10 | ## Features 11 | 12 | 1. **Text and Image Queries**: Gemini-Bot allows users to make both text and image queries to the Gemini AI platform. 13 | 2. **Session Storage**: User queries and corresponding answers are stored in the sessionStorage, ensuring that chats are retained even after page reloads. 14 | 3. **Fetch API**: The Fetch API is used to send requests to the Flask server, enabling seamless communication without page reloads. 15 | 16 | ## Getting Started 17 | 18 | ### Requirements 19 | 20 | - Web browser (Chrome, Firefox, Safari, etc.) 21 | - Internet connection 22 | 23 | ### Installation 24 | 25 | 1. Clone the Gemini-Bot repository from GitHub. 26 | ```bash 27 | git clone https://github.com/yashksaini-coder/Gemini-Bot 28 | ``` 29 | 2. Navigate to the Gemini-Bot directory. 30 | ```bash 31 | cd Gemini-Bot 32 | ``` 33 | 3. Install the packages from requirements.txt 34 | ```bash 35 | pip install -r requirements.txt 36 | ``` 37 | 4. Run `python app.py` from your preferred terminal. 38 | 39 | ### Usage 40 | 41 | 1. **Text Queries**: 42 | - Enter your text query in the text input field. 43 | - Press the "Send" button or hit Enter to submit the query. 44 | - View the response from the Gemini AI platform in the chat interface. 45 | 46 | 2. **Image Queries**: 47 | - Click the "Upload Image" button. 48 | - Select an image file from your device. 49 | - Enter your specific query for the image. 50 | - Wait for the response from the Gemini AI platform, which will be displayed in the chat interface. 51 | 52 | 3. **Session Storage**: 53 | - User queries and responses are stored in sessionStorage. 54 | - This ensures that chats are retained even if the page is reloaded or navigated away from. 55 | 56 | 4. **Fetch API**: 57 | - The Fetch API is used to send requests to the Flask server. 58 | - This communication method avoids page reloads, providing a smoother user experience. 59 | 60 | 3. **API Key**: 61 | - Please obtain your own API key from the Gemini AI platform at [https://ai.google.dev/](https://ai.google.dev/). 62 | - Replace the placeholder API key in the (`.env`) file with your own API key for proper functionality. 63 | # Contributing and Maintaining 64 | 65 | Thank you for your interest in contributing to the Gemini-Bot repository! Your contributions are highly appreciated. This document provides guidelines on how to contribute to the project and how to keep your fork up-to-date with the original repository. 66 | 67 | ## Contributing 68 | 69 | To contribute to the Gemini-Bot repository, please follow these steps: 70 | 71 | 1. **Fork the Repository**: Click on the [Fork](https://github.com/yashksaini-coder/Gemini-Bot/fork) button at the top right corner of the repository page. This will create a copy of the repository in your GitHub account. 72 | 73 | 2. **Clone the Repository**: Clone the forked repository to your local machine using the following command: 74 | ```bash 75 | git clone https://github.com/your-username/Gemini-Bot.git 76 | ``` 77 | Replace `your-username` with your GitHub username. 78 | 79 | 3. **Create a New Branch**: Create a new branch for your changes using the following command: 80 | ```bash 81 | git checkout -b feature-branch-name 82 | ``` 83 | Replace `feature-branch-name` with a descriptive name for your branch. 84 | 85 | 4. **Make Changes**: Make your desired changes to the codebase. 86 | 87 | 5. **Commit Changes**: Commit your changes using the following commands: 88 | ```bash 89 | git add . 90 | git commit -m "Describe your changes" 91 | ``` 92 | 93 | 6. **Push Changes to GitHub**: Push your changes to your forked repository on GitHub using the following command: 94 | ```bash 95 | git push origin feature-branch-name 96 | ``` 97 | 98 | 7. **Create a Pull Request**: Navigate to your forked repository on GitHub and click on the "Compare & pull request" button. Provide a descriptive title and detailed description of your changes, then submit the pull request. 99 | 100 | ## Keeping Your Fork Up-to-Date 101 | 102 | To keep your fork up-to-date with the original repository, follow these steps: 103 | 104 | 1. **Add the Original Repository as a Remote**: Add the original repository as a remote to your local repository using the following command: 105 | ```bash 106 | git remote add upstream https://github.com/yashksaini-coder/Gemini-Bot 107 | ``` 108 | 109 | 2. **Fetch Updates from the Original Repository**: Fetch the latest updates from the original repository using the following command: 110 | ```bash 111 | git fetch upstream 112 | ``` 113 | 114 | 3. **Merge Updates into Your Fork**: Switch to the main branch of your local repository and merge the updates from the original repository using the following commands: 115 | ```bash 116 | git checkout main 117 | git merge upstream/main 118 | ``` 119 | 120 | 4. **Push Updates to Your GitHub Fork**: Push the updates to your forked repository on GitHub using the following command: 121 | ```bash 122 | git push origin main 123 | ``` 124 | Thank you for your contributions and happy coding! 🚀 125 | -------------------------------------------------------------------------------- /__pycache__/app.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yashksaini-coder/Gemini-Bot/ad983b79da0b261591b454b6136e86ad61aff645/__pycache__/app.cpython-312.pyc -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, redirect, render_template, url_for, request, jsonify 2 | from dotenv import load_dotenv 3 | import google.generativeai as genai 4 | from PIL import Image 5 | import os 6 | from markdown import markdown 7 | 8 | load_dotenv('.env') 9 | genai.configure(api_key=os.getenv('API_KEY')) 10 | 11 | model = genai.GenerativeModel('gemini-pro') 12 | chat_model = model.start_chat(history=[]) # chat based on history 13 | 14 | img_model = genai.GenerativeModel('gemini-pro-vision') 15 | 16 | app = Flask(__name__) 17 | 18 | 19 | @app.route("/") 20 | def home(): 21 | return render_template("index.html") 22 | 23 | # Text to text 24 | 25 | 26 | @app.route("/chat", methods=['GET', 'POST']) 27 | def chat(): 28 | if request.method == 'POST': 29 | query = request.json['query'] 30 | if (len(query.strip()) == 0): 31 | return jsonify("Please enter something!") 32 | try: 33 | gemini_response = chat_model.send_message( 34 | query).text # Send message based on the chat history 35 | except: 36 | return jsonify("Something went wrong!") 37 | 38 | return jsonify(markdown(gemini_response)) 39 | else: 40 | return render_template("chats.html") 41 | 42 | # Image to text 43 | 44 | 45 | @app.route("/image_chat", methods=['POST', 'GET']) 46 | def image_chat(): 47 | if request.method == 'POST': 48 | img = request.files['image'] # Loads the file 49 | q = request.form['query'] # Loads the query 50 | 51 | image = Image.open(img) # Read the image in PIL format 52 | try: 53 | response = img_model.generate_content( 54 | [q, image]) # Generate content for the image 55 | except: # noqa: E722 56 | return jsonify("Something went wrong!") 57 | return jsonify(markdown(response.text)) 58 | else: 59 | return render_template("image_upload.html") 60 | 61 | 62 | if __name__ == "__main__": 63 | app.run(port=8080, debug=True) 64 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Flask==3.0.3 2 | Gunicorn 3 | Markdown==3.4.4 4 | google-generativeai==0.3.2 5 | Pillow==9.5.0 6 | protobuf 7 | python-dotenv==1.0.1 -------------------------------------------------------------------------------- /static/ai_bot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yashksaini-coder/Gemini-Bot/ad983b79da0b261591b454b6136e86ad61aff645/static/ai_bot.png -------------------------------------------------------------------------------- /static/css/image_text.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Cabin:ital,wght@0,400..700;1,400..700&family=Mukta:wght@200;300;400;500;600;700;800&family=Mulish:ital,wght@0,200..1000;1,200..1000&family=Nunito:ital,wght@0,200..1000;1,200..1000&family=Roboto+Condensed:ital,wght@0,100..900;1,100..900&family=Ubuntu:ital,wght@0,300;0,400;0,500;0,700;1,300;1,400;1,500;1,700&display=swap'); 2 | input#image{ 3 | display: none; 4 | } 5 | div.user img#query_img, div.user img#query_temp_img{ 6 | margin-top: 0.8rem !important; 7 | height: 150px; 8 | border-radius: 10px !important; 9 | } 10 | div.user img#query_temp_img{ 11 | margin-bottom: 1.5rem; 12 | } 13 | div#query_area button#submit, div#query_area label[for='image']{ 14 | position: absolute; 15 | height: min-content; 16 | padding: 0 !important; 17 | background-color: rgb(255, 255, 255); 18 | display: flex; 19 | justify-content: center; 20 | align-items: center; 21 | margin-top: auto; 22 | margin-bottom: auto; 23 | outline: none; 24 | padding: 0.1rem 0.2rem !important; 25 | border: none; 26 | border-radius: 5px; 27 | cursor: pointer; 28 | z-index: 7; 29 | color: rgb(0, 0, 0); 30 | } 31 | div#query_area button#submit{ 32 | right: 0.85rem 33 | } 34 | div#query_area label[for='image']{ 35 | right: 3.3rem; 36 | } 37 | div.chat div.user p{ 38 | margin-top: 0.3rem; 39 | } 40 | @media screen and (max-width: 640px) { 41 | div.user img#query_img, div.user img#query_temp_img{ 42 | height: 120px; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /static/css/root.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Cabin:ital,wght@0,400..700;1,400..700&family=Mukta:wght@200;300;400;500;600;700;800&family=Mulish:ital,wght@0,200..1000;1,200..1000&family=Nunito:ital,wght@0,200..1000;1,200..1000&family=Roboto+Condensed:ital,wght@0,100..900;1,100..900&family=Ubuntu:ital,wght@0,300;0,400;0,500;0,700;1,300;1,400;1,500;1,700&display=swap'); 2 | *{ 3 | padding: 0; 4 | margin: 0; 5 | } 6 | body{ 7 | width: 100vw; 8 | min-height: 100vh; 9 | background-color: rgb(31, 31, 31); 10 | color: white; 11 | font-family: "Mulish", sans-serif; 12 | display: flex; 13 | justify-content: center; 14 | align-items: center; 15 | overflow-x: hidden; 16 | overflow-y: auto; 17 | } 18 | div.container{ 19 | width: 50vw; 20 | min-height: 80vh; 21 | padding: 1rem; 22 | box-sizing: border-box; 23 | /* border: 1px solid rgba(255, 255, 255, 0.521); 24 | border-radius: 1rem; */ 25 | display: flex; 26 | flex-direction: column; 27 | align-items: center; 28 | justify-content: space-around; 29 | gap: 1.5rem; 30 | } 31 | div.container div#logo_desc{ 32 | display: flex; 33 | flex-direction: column; 34 | justify-content: center; 35 | align-items: center; 36 | /* outline: 2px solid green; */ 37 | } 38 | div.container div#logo_desc p{ 39 | margin-top: 1.2rem; 40 | font-size: 1.4rem; 41 | text-align: center; 42 | } 43 | div.container div#logo_desc p span{ 44 | font-weight: 400; 45 | font-size: 1.8rem; 46 | background: #00FF00; 47 | background: linear-gradient(to left, #ad1ca6 0%, #00FFFF 100%); 48 | -webkit-background-clip: text; 49 | -webkit-text-fill-color: transparent; 50 | background-clip: text; 51 | text-decoration-color: transparent; 52 | } 53 | 54 | div.container div#logo_desc img{ 55 | height: 13rem; 56 | width: 15rem; 57 | aspect-ratio: 1; 58 | } 59 | 60 | div.container div#links{ 61 | width: 100%; 62 | height: 35%; 63 | display: flex; 64 | justify-content: space-evenly; 65 | align-items: center; 66 | flex-wrap: wrap; 67 | gap: 1.5rem; 68 | /* outline: 1px solid red; */ 69 | } 70 | div.container div#links a{ 71 | display: inline-flex; 72 | flex-direction: column; 73 | padding: 0.5rem 1rem; 74 | width: 13.5rem; 75 | aspect-ratio: 1.5/1; 76 | box-sizing: border-box; 77 | border-radius: 10px; 78 | color: white; 79 | text-decoration: none; 80 | justify-content: space-evenly; 81 | align-items: center; 82 | text-align: center; 83 | transition: all 0.15s ease-out; 84 | } 85 | div.container div#links a i{ 86 | font-size: 3rem; 87 | } 88 | div.container div#links a:nth-child(1){ 89 | background: #4776E6; /* fallback for old browsers */ 90 | background: -webkit-linear-gradient(to right, #8E54E9, #4776E6); /* Chrome 10-25, Safari 5.1-6 */ 91 | background: linear-gradient(to right, #8E54E9, #4776E6); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */ 92 | 93 | } 94 | div.container div#links a:nth-child(2){ 95 | background: #ec008c; /* fallback for old browsers */ 96 | background: -webkit-linear-gradient(to right, #fc6767, #ec008c); /* Chrome 10-25, Safari 5.1-6 */ 97 | background: linear-gradient(to right, #fc6767, #ec008c); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */ 98 | } 99 | div.container div#links a:hover{ 100 | transform: scale(0.95); 101 | } 102 | 103 | @media screen and (max-width: 640px) { 104 | div.container{ 105 | width: 90vw !important; 106 | min-height: 85vh; 107 | flex-direction: column; 108 | justify-content: space-evenly; 109 | } 110 | div.container div#logo_desc img{ 111 | height: 9rem; 112 | } 113 | div.container div#logo_desc p{ 114 | font-size: 1rem; 115 | } 116 | div.container div#logo_desc p span{ 117 | font-size: 1.2rem; 118 | } 119 | div.container div#links{ 120 | flex-direction: column; 121 | gap: 1.5rem; 122 | } 123 | div.container div#links a{ 124 | width: 66%; 125 | aspect-ratio: 1.6/1; 126 | } 127 | div.container div#links a i{ 128 | font-size: 2rem; 129 | } 130 | } -------------------------------------------------------------------------------- /static/css/style.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Cabin:ital,wght@0,400..700;1,400..700&family=Mukta:wght@200;300;400;500;600;700;800&family=Mulish:ital,wght@0,200..1000;1,200..1000&family=Nunito:ital,wght@0,200..1000;1,200..1000&family=Roboto+Condensed:ital,wght@0,100..900;1,100..900&family=Ubuntu:ital,wght@0,300;0,400;0,500;0,700;1,300;1,400;1,500;1,700&display=swap'); 2 | *{ 3 | margin: 0; 4 | padding: 0; 5 | font-family: "Mulish", sans-serif; 6 | } 7 | body{ 8 | width: 100vw; 9 | background-color: rgb(36, 36, 37); 10 | color: white; 11 | overflow-x: hidden; 12 | } 13 | header{ 14 | width: 100vw; 15 | display: flex; 16 | justify-content: space-between; 17 | align-items: center; 18 | padding: 0.5rem; 19 | height: 3.5rem; 20 | font-size: 1.25rem; 21 | background-color: rgb(31, 31, 31); 22 | color: white; 23 | position: fixed; 24 | top: 0; 25 | z-index: 8; 26 | } 27 | header div#home{ 28 | width: 2rem; 29 | margin-left: 1rem; 30 | position: absolute; 31 | top: auto; 32 | aspect-ratio: 1/1; 33 | z-index: 10; 34 | } 35 | header div#home a{ 36 | width: 100%; 37 | height: 100%; 38 | font-size: 1.7rem; 39 | display: flex; 40 | justify-content: center; 41 | align-items: center; 42 | color: white; 43 | text-decoration: none; 44 | } 45 | header div#chat_options{ 46 | width: 100%; 47 | /* outline: 1px solid red; */ 48 | font-size: 1.1rem; 49 | display: flex; 50 | justify-content: center; 51 | align-items: center; 52 | position: relative; 53 | } 54 | div#chat_options p{ 55 | display: flex; 56 | cursor: pointer; 57 | align-items: center; 58 | padding: 0.5rem 1rem; 59 | border-radius: 5px; 60 | border: 0.7px solid rgba(255, 255, 255, 0.511); 61 | background-color: rgb(44, 43, 43); 62 | } 63 | div#chat_options p:hover{ 64 | background-color: rgb(36, 35, 35); 65 | } 66 | div#chat_options p i{ 67 | margin-left: 0.5rem; 68 | font-size: 0.8rem; 69 | transition: all 0.12s ease-in; 70 | } 71 | div#chat_options ul{ 72 | position: absolute; 73 | top: 2.8rem; 74 | border-radius: 5px; 75 | border: 0.7px solid rgba(255, 255, 255, 0.511); 76 | background-color: rgb(31, 31, 31); 77 | overflow: hidden; 78 | display: none; 79 | transition: all 0.2s ease-in; 80 | } 81 | div#chat_options ul li{ 82 | list-style-type: none; 83 | } 84 | div#chat_options ul li a{ 85 | display: block; 86 | padding: 0.5rem 2.3rem 0.5rem 0.8rem; 87 | color: white; 88 | text-decoration: none; 89 | } 90 | div#chat_options ul li a:hover{ 91 | background-color: rgb(44, 43, 43); 92 | } 93 | div#query_area{ 94 | display: flex; 95 | justify-content: center; 96 | position: fixed; 97 | background-color: rgb(31, 31, 31); 98 | bottom: 0; 99 | box-sizing: border-box; 100 | padding: 1rem; 101 | width: 100%; 102 | } 103 | div#query_area div.text_btn{ 104 | width: 50%; 105 | display: flex; 106 | justify-content: center; 107 | align-items: center; 108 | position: relative; 109 | } 110 | div#query_area textarea{ 111 | min-height: 2.2rem; 112 | padding: 0.75rem 0.7rem; 113 | border: 1px solid grey; 114 | /* overflow-y: auto; */ 115 | border-radius: 10px; 116 | outline: none; 117 | font-size: 0.95rem; 118 | width: 100%; 119 | background-color: rgb(44, 43, 43); 120 | color: white; 121 | resize: none; 122 | } 123 | div#query_area button#submit{ 124 | position: absolute; 125 | height: min-content; 126 | padding: 0 !important; 127 | background-color: rgb(255, 255, 255); 128 | display: flex; 129 | justify-content: center; 130 | align-items: center; 131 | margin-top: auto; 132 | margin-bottom: auto; 133 | outline: none; 134 | padding: 0.1rem 0.2rem !important; 135 | border: none; 136 | border-radius: 5px; 137 | cursor: pointer; 138 | color: rgb(0, 0, 0); 139 | right: 1rem; 140 | } 141 | div#query_area button#submit span{ 142 | padding: 0 !important; 143 | } 144 | div.chats{ 145 | margin: 6rem auto; 146 | width: 65vw; 147 | display: flex; 148 | flex-direction: column; 149 | } 150 | 151 | div.chats div.chat{ 152 | margin-bottom: 1.35rem; 153 | } 154 | div.chat div.user{ 155 | margin-bottom: 1.05rem; 156 | } 157 | div.chat div.user span, div.chat div.gemini span{ 158 | font-weight: 700; 159 | } 160 | div.user div:nth-child(1), div.gemini div:nth-child(1){ 161 | display: flex; 162 | align-items: center; 163 | gap: 10px; 164 | } 165 | div.user img.avatar, div.gemini img.avatar{ 166 | height: 27px; 167 | aspect-ratio: 1; 168 | border-radius: 50%; 169 | background-color: rgb(28, 27, 27); 170 | outline: 0.1px solid rgba(255, 255, 255, 0.687); 171 | } 172 | div.chat div.user p, div.chat div.gemini p{ 173 | margin-top: 0.5rem; 174 | } 175 | div.gemini p a{ 176 | color: rgb(0, 119, 255); 177 | } 178 | div.gemini p a:hover{ 179 | text-decoration: none; 180 | } 181 | div.chats div.chat h4:nth-child(2){ 182 | margin-top: 0.5rem; 183 | } 184 | div.user p, div.gemini p{ 185 | line-height: 1.5; 186 | } 187 | div#loading_div{ 188 | display: flex; 189 | align-items: center; 190 | } 191 | span#loading{ 192 | display: inline-block; 193 | width: 1rem; 194 | height: 1rem; 195 | border: 3px solid rgb(132, 132, 132); 196 | border-top: 3px solid white; 197 | animation: loading 0.35s linear infinite; 198 | border-radius: 50%; 199 | } 200 | @keyframes loading { 201 | from{ 202 | transform: rotate(0); 203 | }to{ 204 | transform: rotate(360deg); 205 | } 206 | } 207 | @media screen and (max-width: 640px){ 208 | header{ 209 | height: 3rem; 210 | } 211 | header div#home{ 212 | margin-left: 0.5rem; 213 | } 214 | header div#home a{ 215 | font-size: 1.5rem; 216 | } 217 | div#chat_options p{ 218 | padding: 0.4rem 0.9rem; 219 | font-size: 1rem; 220 | } 221 | div#chat_options ul{ 222 | font-size: 1rem; 223 | } 224 | div.chats{ 225 | width: 75vw; 226 | margin: 5rem auto; 227 | } 228 | 229 | div#query_area{ 230 | justify-content: center; 231 | bottom: -1px; 232 | } 233 | div#query_area textarea{ 234 | padding: 0.5rem 0.7rem; 235 | } 236 | div#query_area div.text_btn{ 237 | width: 90%; 238 | } 239 | } -------------------------------------------------------------------------------- /static/js/additional.js: -------------------------------------------------------------------------------- 1 | let chat_options = document.getElementById("selected_option") 2 | let options = document.getElementById("options") 3 | let down_arrow = document.querySelector("div#chat_options p i") 4 | 5 | chat_options.addEventListener("click", () => { 6 | if (chat_options.classList.contains("opened")) { 7 | options.style.display = "none"; 8 | down_arrow.style.transform = "rotate(0)" 9 | } else { 10 | options.style.display = "block"; 11 | down_arrow.style.transform = "rotate(-180deg)" 12 | } 13 | chat_options.classList.toggle("opened") 14 | }) 15 | -------------------------------------------------------------------------------- /static/js/app.js: -------------------------------------------------------------------------------- 1 | let text_area = document.querySelector('textarea') 2 | let all_chats = document.querySelector('div.chats') 3 | let ask_btn = document.querySelector('button#submit') 4 | 5 | // Get response via fetch from the server 6 | async function get_response(query) { 7 | let response = await fetch("/chat", { 8 | headers: { 9 | 'Content-type': 'application/json' 10 | }, 11 | method: 'POST', 12 | body: JSON.stringify({ query }) 13 | }) 14 | return response.json() 15 | } 16 | 17 | ask_btn.addEventListener("click", async () => { 18 | 19 | let query = text_area.value; 20 | text_area.value = "" 21 | ask_btn.disabled = true 22 | ask_btn.firstElementChild.style.opacity = "0.8" 23 | let new_query = document.createElement('div') 24 | new_query.setAttribute("class", "chat") 25 | 26 | // User part 27 | let user_query = document.createElement('div') 28 | user_query.setAttribute('class', 'user') 29 | let user_avatar_div = document.createElement('div') 30 | user_avatar_div.innerHTML = ` You` 31 | let user_question = document.createElement('p') 32 | user_question.innerText = query 33 | user_query.append(user_avatar_div, user_question) 34 | 35 | // Gemini-Bot/Gemini part 36 | let gemini_response = document.createElement('div') 37 | gemini_response.setAttribute('class', 'gemini') 38 | let gemini_avatar_div = document.createElement('div') 39 | gemini_avatar_div.innerHTML = ` Gemini-Bot` 40 | let gemini_ans = document.createElement('p') 41 | gemini_ans.innerHTML = "
Generating your content
" 42 | gemini_response.append(gemini_avatar_div, gemini_ans) 43 | 44 | new_query.append(user_query) 45 | new_query.append(gemini_response) 46 | all_chats.append(new_query) 47 | 48 | gemini_ans.innerHTML = await get_response(query) 49 | text_area.value = "" 50 | ask_btn.disabled = false 51 | ask_btn.firstElementChild.style.opacity = "1" 52 | 53 | // To retrieve all the items after refresh, using sessionStorage to store them 54 | // Using array to maintain the order of the chats 55 | setTimeout(() => { 56 | // query_array_7_48 contains all the chats 57 | // if query_array_7_48 is present, get it & push the new query 58 | // else create query_array_7_48 with the first query 59 | if (sessionStorage.getItem("query_array_7_48")) { 60 | let queries = JSON.parse(sessionStorage.getItem("query_array_7_48")) 61 | queries.push(new_query.outerHTML) 62 | sessionStorage.setItem("query_array_7_48", JSON.stringify(queries)) 63 | } else { 64 | sessionStorage.setItem("query_array_7_48", JSON.stringify([new_query.outerHTML])) 65 | } 66 | }, 0) // This part is important to block this line execution upto all the synchronous part is executed 67 | 68 | }) 69 | 70 | text_area.addEventListener("keydown", (event) => { 71 | if (event.key == 'Enter') { 72 | ask_btn.click() 73 | } 74 | }) 75 | 76 | window.addEventListener("load", () => { 77 | let whole_html = "" 78 | 79 | // retrieve the array and take all the queries that was stored, then use it 80 | if (sessionStorage.getItem("query_array_7_48")) { 81 | let queries = JSON.parse(sessionStorage.getItem("query_array_7_48")) 82 | for (query of queries) { 83 | whole_html += query 84 | } 85 | } 86 | all_chats.innerHTML = whole_html 87 | 88 | }) -------------------------------------------------------------------------------- /static/js/image_chat.js: -------------------------------------------------------------------------------- 1 | let image = document.getElementById("image") 2 | let image_label = document.querySelector("label[for='image']") 3 | let text_area = document.querySelector('textarea') 4 | let ask_btn = document.querySelector('button#submit') 5 | let all_chats = document.querySelector('div.chats') 6 | 7 | var imgUrl = null; 8 | var loadedImg = null; 9 | 10 | // To send a fetch request to the server at specific endpoint 11 | async function get_response(data) { 12 | 13 | let response = await fetch("/image_chat", { 14 | method: 'POST', 15 | body: data 16 | }) 17 | return response.json() 18 | } 19 | 20 | ask_btn.addEventListener("click", async function () { 21 | if (imgUrl) { 22 | // Remove the temp image div 23 | try { 24 | document.getElementById("temp-user-query").remove() 25 | } catch (err) { 26 | 27 | } 28 | 29 | let query = text_area.value; 30 | text_area.value = "" 31 | 32 | const formData = new FormData(); 33 | formData.append('image', loadedImg); // using the last successfully loaded image that was created during input event 34 | formData.append('query', query); 35 | 36 | ask_btn.firstElementChild.style.opacity = "0.8" 37 | ask_btn.disabled = true 38 | ask_btn.style.cursor = 'not-allowed' 39 | 40 | image_label.firstElementChild.style.opacity = "0.8" 41 | image_label.disabled = true 42 | image_label.style.cursor = 'not-allowed' 43 | 44 | let new_query = document.createElement('div') 45 | new_query.setAttribute("class", "chat") 46 | 47 | // User part 48 | let user_query = document.createElement('div') 49 | user_query.setAttribute('class', 'user') 50 | let user_avatar_div = document.createElement('div') 51 | user_avatar_div.innerHTML = ` You` 52 | let user_img_query = document.createElement('img') 53 | user_img_query.setAttribute('id', "query_img") 54 | user_img_query.src = `${imgUrl}` // using the image url that was created during input event 55 | let user_question = document.createElement('p') 56 | user_question.innerText = query 57 | user_query.append(user_avatar_div, user_img_query, user_question) 58 | 59 | // Gemini-Bot/Gemini part 60 | let gemini_response = document.createElement('div') 61 | gemini_response.setAttribute('class', 'gemini') 62 | let gemini_avatar_div = document.createElement('div') 63 | gemini_avatar_div.innerHTML = ` Gemini-Bot` 64 | let gemini_ans = document.createElement('p') 65 | gemini_ans.innerHTML = "
Generating your content
" 66 | gemini_response.append(gemini_avatar_div, gemini_ans) 67 | 68 | // Creating new_query 69 | new_query.append(user_query) 70 | new_query.append(gemini_response) 71 | 72 | // Appending the new queries in to chats 73 | all_chats.append(new_query) 74 | 75 | gemini_ans.innerHTML = await get_response(formData) 76 | text_area.value = "" 77 | 78 | ask_btn.firstElementChild.style.opacity = "1" 79 | ask_btn.disabled = false 80 | ask_btn.style.cursor = 'pointer' 81 | 82 | image_label.firstElementChild.style.opacity = "1" 83 | image_label.disabled = false 84 | image_label.style.cursor = 'pointer' 85 | 86 | imgUrl = null; // remove the previous picture once it has been queried 87 | 88 | // To retrieve all the items after refresh, using sessionStorage to store them 89 | // Using array to maintain the order of the chats 90 | setTimeout(() => { 91 | // query_array_7_48 contains all the chats 92 | // if query_array_7_48 is present, get it & push the new query 93 | // else create query_array_7_48 with the first query 94 | if (sessionStorage.getItem("query_img_array_7_48")) { 95 | let queries = JSON.parse(sessionStorage.getItem("query_img_array_7_48")) 96 | queries.push(new_query.outerHTML) 97 | sessionStorage.setItem("query_img_array_7_48", JSON.stringify(queries)) 98 | } else { 99 | sessionStorage.setItem("query_img_array_7_48", JSON.stringify([new_query.outerHTML])) 100 | } 101 | }, 0) // This part is important to block this line execution upto all the synchronous part is executed 102 | } else { 103 | alert("Please upload an image!") 104 | } 105 | }) 106 | 107 | // Show the image when the user uploads it (temporarily) 108 | image.addEventListener("change", () => { 109 | 110 | try { 111 | let img = image.files[0] 112 | let img_url = URL.createObjectURL(img) // may throw error if the image is not uploaded 113 | 114 | loadedImg = img; 115 | imgUrl = img_url; 116 | try { 117 | document.getElementById("temp-user-query").remove() 118 | } catch (err) { 119 | 120 | } 121 | let user_query = document.createElement('div') 122 | user_query.setAttribute('class', 'user') 123 | user_query.setAttribute('id', 'temp-user-query') 124 | let user_avatar_div = document.createElement('div') 125 | user_avatar_div.innerHTML = ` You` 126 | let user_img_query = document.createElement('img') 127 | user_img_query.setAttribute('id', "query_temp_img") 128 | user_img_query.src = `${img_url}` 129 | user_img_query.style.opacity = "0.8" 130 | user_query.append(user_avatar_div, user_img_query) 131 | 132 | all_chats.append(user_query) 133 | } catch (err) { 134 | console.log(err) 135 | imgUrl = null; 136 | } 137 | }) 138 | 139 | text_area.addEventListener("keydown", (event) => { 140 | if (event.key == 'Enter') { 141 | ask_btn.click() 142 | } 143 | }) 144 | 145 | // Function to load/retain all the chats when the page is refreshed/loaded 146 | window.addEventListener("load", () => { 147 | let whole_html = "" 148 | // retrieve the array and take all the queries that was stored, then use it 149 | if (sessionStorage.getItem("query_img_array_7_48")) { 150 | let queries = JSON.parse(sessionStorage.getItem("query_img_array_7_48")) 151 | for (query of queries) { 152 | whole_html += query 153 | } 154 | } 155 | all_chats.innerHTML = whole_html 156 | }) -------------------------------------------------------------------------------- /static/person_avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yashksaini-coder/Gemini-Bot/ad983b79da0b261591b454b6136e86ad61aff645/static/person_avatar.png -------------------------------------------------------------------------------- /templates/chats.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Text to text 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 | 16 | 17 | 18 |
19 |
20 |

Text to text

21 | 25 |
26 |
27 |
28 |
29 |
30 |
31 | 32 | 37 |
38 |
39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /templates/image_upload.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Image to Text 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 | 17 | 18 | 19 |
20 |
21 |

Image to text

22 | 26 |
27 |
28 |
29 |
30 |
31 |
32 | 33 | 34 | 39 | 44 |
45 |
46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Gemini-Bot 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 | 17 |

Gemini Bot: Simple & Light-weight flask based AI bot .

18 |
19 | 33 |
34 | 35 | -------------------------------------------------------------------------------- /vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "builds": [ 4 | {"src": "app.py", "use": "@vercel/python"} 5 | ], 6 | "routes": [ 7 | {"src": "/(.*)", "dest": "app.py"} 8 | ] 9 | } --------------------------------------------------------------------------------