├── Server ├── .gitignore ├── requirements.txt ├── Dockerfile ├── docker-compose.yml ├── load_creds.py └── app.py ├── .gitignore ├── README.md ├── images ├── explain.jpg ├── chatbot_interface.png ├── image_generation.png └── pdf_context_loader.png ├── .idea ├── .gitignore ├── jsLibraryMappings.xml ├── inspectionProfiles │ ├── profiles_settings.xml │ └── Project_Default.xml ├── modules.xml ├── misc.xml ├── ai_chatbot.iml └── vcs.xml ├── AI_Chatbot ├── src │ ├── index.css │ ├── main.jsx │ ├── assets │ │ └── react.svg │ ├── App.css │ └── App.jsx ├── index.html ├── .gitignore ├── vite.config.js ├── README.md ├── .eslintrc.cjs ├── api │ └── proxy.js ├── package.json └── public │ └── vite.svg └── LICENSE /Server/.gitignore: -------------------------------------------------------------------------------- 1 | venv -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.env 2 | Server/service-account-file.json -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AI_powered_Chatbot.github.io 2 | An Project with Deep learning and Machine learning algorithms 3 | -------------------------------------------------------------------------------- /images/explain.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Naveenk069/AI_powered_Chatbot.github.io/main/images/explain.jpg -------------------------------------------------------------------------------- /Server/requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Naveenk069/AI_powered_Chatbot.github.io/main/Server/requirements.txt -------------------------------------------------------------------------------- /images/chatbot_interface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Naveenk069/AI_powered_Chatbot.github.io/main/images/chatbot_interface.png -------------------------------------------------------------------------------- /images/image_generation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Naveenk069/AI_powered_Chatbot.github.io/main/images/image_generation.png -------------------------------------------------------------------------------- /images/pdf_context_loader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Naveenk069/AI_powered_Chatbot.github.io/main/images/pdf_context_loader.png -------------------------------------------------------------------------------- /Server/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3-alpine3.18 2 | WORKDIR /api 3 | COPY . /api 4 | RUN pip install --no-cache-dir -r requirements.txt 5 | EXPOSE 8000 6 | CMD ["python", "main.py"] -------------------------------------------------------------------------------- /Server/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.7' 2 | 3 | services: 4 | server: 5 | build: 6 | context: . 7 | dockerfile: Dockerfile 8 | ports: 9 | - "8000:8000" -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /.idea/jsLibraryMappings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /AI_Chatbot/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | color: white; 5 | font-family: 'Roboto', sans-serif; 6 | background-color: #323232; 7 | } 8 | 9 | html { 10 | box-sizing: border-box; 11 | padding: 0; 12 | margin: 0; 13 | } -------------------------------------------------------------------------------- /AI_Chatbot/src/main.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | import App from './App.jsx' 4 | import './index.css' 5 | 6 | ReactDOM.createRoot(document.getElementById('root')).render( 7 | 8 | 9 | , 10 | ) 11 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AI_Chatbot/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | AI-Chatbot 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /AI_Chatbot/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | *.env -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 10 | -------------------------------------------------------------------------------- /AI_Chatbot/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | server: { 8 | proxy: { 9 | '/api': { 10 | target: 'http://ec2-3-95-219-188.compute-1.amazonaws.com:8000', 11 | changeOrigin: true, 12 | rewrite: (path) => path.replace(/^\/api/, ''), 13 | }, 14 | }, 15 | }, 16 | }) 17 | -------------------------------------------------------------------------------- /.idea/ai_chatbot.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /AI_Chatbot/README.md: -------------------------------------------------------------------------------- 1 | # React + Vite 2 | 3 | This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. 4 | 5 | Currently, two official plugins are available: 6 | 7 | - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh 8 | - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh 9 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /AI_Chatbot/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { browser: true, es2020: true }, 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:react/recommended', 7 | 'plugin:react/jsx-runtime', 8 | 'plugin:react-hooks/recommended', 9 | ], 10 | ignorePatterns: ['dist', '.eslintrc.cjs'], 11 | parserOptions: { ecmaVersion: 'latest', sourceType: 'module' }, 12 | settings: { react: { version: '18.2' } }, 13 | plugins: ['react-refresh'], 14 | rules: { 15 | 'react/jsx-no-target-blank': 'off', 16 | 'react-refresh/only-export-components': [ 17 | 'warn', 18 | { allowConstantExport: true }, 19 | ], 20 | }, 21 | } 22 | -------------------------------------------------------------------------------- /AI_Chatbot/api/proxy.js: -------------------------------------------------------------------------------- 1 | import fetch from 'node-fetch'; 2 | 3 | export default async (req, res) => { 4 | try { 5 | const formData = new FormData(); 6 | 7 | for (const key in req.body) { 8 | formData.append(key, req.body[key]); 9 | } 10 | 11 | if (req.body.file) { 12 | formData.append('file', req.body.file); 13 | } 14 | 15 | const response = await fetch('http://ec2-3-95-219-188.compute-1.amazonaws.com:8000/chat', { 16 | method: 'POST', 17 | headers: { 18 | 'Content-Type': req.headers['content-type'], 19 | ...req.headers, 20 | }, 21 | body: formData, 22 | }); 23 | 24 | const contentType = response.headers.get('content-type'); 25 | let data; 26 | if (contentType && contentType.includes('application/json')) { 27 | data = await response.json(); 28 | } else { 29 | data = await response.text(); 30 | } 31 | 32 | res.status(response.status).send(data); 33 | } catch (error) { 34 | console.error('Error:', error); 35 | res.status(500).send('Error fetching data from backend server'); 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Dr.S.SUJANTHI 4 | Students : NANDHAKUMAR R, NAVEENKUMAR M, SELVA KIRTHICK B and TULASIDHASAN S 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /AI_Chatbot/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chatbot-frontend", 3 | "private": true, 4 | "version": "1.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "@babel/runtime": "^7.24.6", 14 | "assemblyai": "^4.4.5", 15 | "axios": "^1.7.2", 16 | "http-proxy-middleware": "^2.0.0", 17 | "monsterapi": "^0.0.5", 18 | "react": "^18.2.0", 19 | "react-dom": "^18.2.0", 20 | "react-dropzone": "^14.2.3", 21 | "react-hook-speech-to-text": "^0.8.0", 22 | "react-icons": "^5.2.1", 23 | "react-markdown": "^9.0.1", 24 | "react-pdftotext": "^1.3.0", 25 | "react-speech": "^1.0.2", 26 | "react-speech-recognition": "^3.10.0", 27 | "regenerator-runtime": "^0.14.1" 28 | }, 29 | "devDependencies": { 30 | "@babel/plugin-transform-runtime": "^7.24.6", 31 | "@types/react": "^18.2.6", 32 | "@types/react-dom": "^18.2.0", 33 | "@vitejs/plugin-react": "^4.2.1", 34 | "concurrently": "^9.1.0", 35 | "eslint": "^8.57.0", 36 | "eslint-plugin-react": "^7.34.1", 37 | "eslint-plugin-react-hooks": "^4.6.0", 38 | "eslint-plugin-react-refresh": "^0.4.6", 39 | "vite": "^5.2.0" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Server/load_creds.py: -------------------------------------------------------------------------------- 1 | import os.path 2 | 3 | from google.auth.transport.requests import Request 4 | from google.oauth2.credentials import Credentials 5 | from google_auth_oauthlib.flow import InstalledAppFlow 6 | 7 | SCOPES = ['https://www.googleapis.com/auth/generative-language.retriever'] 8 | 9 | 10 | def load_creds(): 11 | """Converts `client_secret.json` to a credential object. 12 | 13 | This function caches the generated tokens to minimize the use of the 14 | consent screen. 15 | """ 16 | creds = None 17 | # The file token.json stores the user's access and refresh tokens, and is 18 | # created automatically when the authorization flow completes for the first 19 | # time. 20 | if os.path.exists('token.json'): 21 | creds = Credentials.from_authorized_user_file('token.json', SCOPES) 22 | # If there are no (valid) credentials available, let the user log in. 23 | if not creds or not creds.valid: 24 | if creds and creds.expired and creds.refresh_token: 25 | creds.refresh(Request()) 26 | else: 27 | flow = InstalledAppFlow.from_client_secrets_file( 28 | 'client_secret.json', SCOPES) 29 | creds = flow.run_local_server(port=0) 30 | # Save the credentials for the next run 31 | with open('token.json', 'w') as token: 32 | token.write(creds.to_json()) 33 | return creds 34 | -------------------------------------------------------------------------------- /AI_Chatbot/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Server/app.py: -------------------------------------------------------------------------------- 1 | import os 2 | from flask import Flask, request, jsonify 3 | import google.generativeai as genai 4 | from dotenv import load_dotenv 5 | from werkzeug.utils import secure_filename 6 | import PIL.Image 7 | 8 | load_dotenv() 9 | app = Flask(__name__) 10 | 11 | AVAILABLE_MODELS = [ 12 | 'models/gemini-1.5-flash', 'models/gemini-1.0-pro', 'models/gemini-1.0-pro-001', 'models/gemini-1.0-pro-latest', 13 | 'models/gemini-1.0-pro-vision-latest', 'models/gemini-1.5-flash-001', 14 | 'models/gemini-1.5-flash-latest', 'models/gemini-1.5-pro', 'models/gemini-1.5-pro-001', 15 | 'models/gemini-1.5-pro-latest', 'models/gemini-pro', 'models/gemini-pro-vision' 16 | ] 17 | 18 | UPLOAD_FOLDER = 'uploads' 19 | app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER 20 | 21 | # Ensure the uploads directory exists 22 | if not os.path.exists(UPLOAD_FOLDER): 23 | os.makedirs(UPLOAD_FOLDER) 24 | 25 | 26 | def clear_uploads_folder(max_files=3): 27 | files = os.listdir(UPLOAD_FOLDER) 28 | if len(files) > max_files: 29 | files_to_delete = files[:-max_files] 30 | for file in files_to_delete: 31 | file_path = os.path.join(UPLOAD_FOLDER, file) 32 | try: 33 | os.remove(file_path) 34 | except Exception as e: 35 | print(f"Error deleting file {file_path}: {e}") 36 | 37 | 38 | @app.after_request 39 | def add_cors_headers(response): 40 | response.headers['Access-Control-Allow-Origin'] = '*' 41 | response.headers['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS' 42 | response.headers['Access-Control-Allow-Headers'] = 'Content-Type' 43 | return response 44 | 45 | 46 | @app.route('/', methods=['GET']) 47 | def home(): 48 | return 'Chatbot Server is running!' 49 | 50 | 51 | @app.route('/chat', methods=['POST']) 52 | def chat(): 53 | clear_uploads_folder() 54 | 55 | data = request.form 56 | file = request.files.get('file') 57 | if not data or 'message' not in data or 'model' not in data: 58 | return jsonify({'error': 'Invalid request: message and model fields are required'}), 400 59 | user_message = data['message'] 60 | context = data.get('context', '') 61 | model_name = data['model'] 62 | gemini_api_key = data.get('geminiApiKey') 63 | 64 | image_path = None 65 | if file: 66 | filename = secure_filename(file.filename) 67 | image_path = os.path.join(app.config['UPLOAD_FOLDER'], filename) 68 | file.save(image_path) 69 | 70 | chatbot_response, image_path = Gemini_response(user_message, context, model_name, image_path, gemini_api_key) 71 | 72 | return jsonify({'response': chatbot_response, 'image_url': image_path if image_path else ''}) 73 | 74 | 75 | def Gemini_response(user_message, context, model_name, image_path=None, api_key=None): 76 | try: 77 | if not api_key: 78 | return "API Key is missing", None 79 | genai.configure(api_key=api_key) 80 | model = genai.GenerativeModel(model_name) 81 | chat = model.start_chat(history=[]) 82 | 83 | if image_path: 84 | img = PIL.Image.open(image_path) 85 | inputs = [user_message, img] 86 | response = model.generate_content(inputs, stream=False) 87 | chatbot_response = response.text 88 | return chatbot_response, image_path 89 | user_message_with_context = user_message + "\n" + context 90 | response = chat.send_message(user_message_with_context, stream=False) 91 | chatbot_response = response.text 92 | return chatbot_response, None 93 | except Exception as e: 94 | return str(e), None 95 | 96 | 97 | if __name__ == '__main__': 98 | app.run(host='0.0.0.0', debug=True) 99 | -------------------------------------------------------------------------------- /AI_Chatbot/src/assets/react.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 95 | -------------------------------------------------------------------------------- /AI_Chatbot/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | font-family: Arial, sans-serif; 3 | text-align: center; 4 | display: flex; 5 | flex-direction: column; 6 | overflow-x: hidden; 7 | } 8 | 9 | .one_p { 10 | height: 100vh; 11 | display: flex; 12 | flex-direction: row; /* Ensures side-by-side layout */ 13 | width: 100%; 14 | } 15 | 16 | .one_p.chat_bot { 17 | flex: 3; /* 60% of the screen */ 18 | display: flex; 19 | flex-direction: column; 20 | align-content: center; 21 | justify-content: center; 22 | padding-left: 20px; 23 | padding-right: 20px; 24 | } 25 | 26 | .pdf-to-text { 27 | flex: 2; /* 40% of the screen */ 28 | display: flex; 29 | flex-direction: column; 30 | padding-left: 20px; 31 | padding-right: 20px; 32 | margin-top: 1.5rem; 33 | margin-bottom: 1.5rem; 34 | } 35 | 36 | .vertical-line { 37 | width: 2px; 38 | background-color: #ccc; 39 | text-align: center; 40 | margin-top: 2rem; 41 | margin-bottom: 2rem; 42 | } 43 | 44 | .title { 45 | align-self: flex-start; 46 | text-align: center; 47 | margin-bottom: 20px; 48 | } 49 | 50 | .parent_chat { 51 | background-color: #808080; 52 | border-radius: 11px; 53 | display: flex; 54 | flex-direction: column; 55 | height: 85%; 56 | } 57 | 58 | .chat-window { 59 | padding: 0.5rem 1rem; 60 | height: 75vh; 61 | background-color: #ffffff; 62 | overflow-x: hidden; 63 | overflow-y: scroll; 64 | border-radius: 10px; 65 | display: flex; 66 | flex-direction: column; 67 | } 68 | 69 | .chat-window::-webkit-scrollbar { 70 | width: 15px; 71 | } 72 | 73 | .chat-window::-webkit-scrollbar-thumb { 74 | background-color: #ccc; 75 | border: 4px solid rgba(0, 0, 0, 0); 76 | border-radius: 9999px; 77 | background-clip: padding-box; 78 | } 79 | 80 | .message { 81 | margin: 0.5rem 0; 82 | border-radius: 10px; 83 | display: inline-block; 84 | max-width: 80%; /* Ensures messages don't take up more than 80% of the container width */ 85 | min-width: 1%; /* Ensures very short messages have a minimum width */ 86 | word-wrap: break-word; /* Ensures long words break to the next line */ 87 | } 88 | 89 | .message.user { 90 | align-self: flex-end; 91 | padding: 0 1rem; 92 | text-align: right; 93 | color: white; 94 | background-color: #2f2f2f; 95 | } 96 | 97 | .message.bot { 98 | align-self: flex-start; 99 | padding: 0 1rem; 100 | text-align: left; 101 | color: white; 102 | background-color: #2f2f2f; 103 | } 104 | 105 | .txt { 106 | margin: 0; 107 | padding: 0.8rem 1rem; 108 | } 109 | 110 | .prompt { 111 | width: 200%; 112 | align-self: center; 113 | border-radius: 11px; 114 | } 115 | 116 | .msg { 117 | border-radius: 50px; 118 | width: 80%; 119 | padding: 10px; 120 | border: 1px solid #ccc; 121 | margin-bottom: 10px 122 | } 123 | 124 | .parent_prompt { 125 | padding-top: 1rem; 126 | width: 100%; 127 | display: flex; 128 | align-items: center; 129 | } 130 | 131 | .msg:focus { 132 | outline: none; 133 | } 134 | 135 | .btn_send { 136 | margin-bottom: 0.6rem; 137 | height: 4rem; 138 | width: 6rem; 139 | transform: translateX(-40px); 140 | background: none; 141 | display: flex; 142 | font-size: 1.8rem; 143 | justify-content: center; 144 | align-items: center; 145 | margin-left: 2rem; 146 | border: none; 147 | } 148 | 149 | .btn_send:focus, .btn_record:focus { 150 | outline: none; 151 | } 152 | 153 | .btn_record { 154 | margin-left: 1rem; 155 | margin-bottom: 0.6rem; 156 | background-color: black; 157 | font-size: 1.7rem; 158 | color: red; 159 | padding: 0.2rem; 160 | transform: translateX(-20px); 161 | display: flex; 162 | justify-content: center; 163 | align-items: center; 164 | border: 0; 165 | border-radius: 50px; 166 | } 167 | 168 | .self_center { 169 | align-self: center; 170 | text-align: center; 171 | } 172 | 173 | .choose_btn { 174 | margin-bottom: 2rem; 175 | } 176 | .choose_btn::-webkit-file-upload-button { 177 | background-color: black; 178 | color: white; 179 | padding: 13px; 180 | border: 0; 181 | margin: 1rem; 182 | border-radius: 5px; 183 | } 184 | /* Styling for the attachment button */ 185 | .btn_attach { 186 | margin-bottom: 0.7rem; 187 | margin-left: 1rem; 188 | background-color: #4CAF50; /* Green background */ 189 | border: none; /* Remove borders */ 190 | color: white; /* White text */ 191 | padding: 5px; /* Padding */ 192 | display: flex; /* Center items */ 193 | font-size: 1.5rem; /* Icon size */ 194 | cursor: pointer; /* Pointer/hand icon on hover */ 195 | border-radius: 50%; /* Rounded shape */ 196 | align-items: center; /* Center items vertically */ 197 | justify-content: center; /* Center items horizontally */ 198 | transition: background-color 0.3s; /* Smooth transition */ 199 | } 200 | 201 | .btn_attach:hover { 202 | background-color: #45a049; /* Darker green background on hover */ 203 | } 204 | 205 | 206 | .choose_btn::-webkit-file-upload-button:hover { 207 | background-color: #4caf50; 208 | } 209 | 210 | .extracted-text { 211 | border: 1px solid #ccc; 212 | color: #1a1a1a; 213 | padding: 10px; 214 | width: 90%; 215 | border-radius: 5px; 216 | background-color: #f9f9f9; 217 | height: 75vh; /* Set a fixed height */ 218 | overflow-y: scroll; /* Enable vertical scrolling */ 219 | } 220 | 221 | .extracted-text pre { 222 | white-space: pre-wrap; 223 | word-wrap: break-word; 224 | } 225 | 226 | .clear_btn { 227 | background-color: black; 228 | color: white; 229 | padding: 10px; 230 | border: 0; 231 | margin-top: 1rem; 232 | margin-right: 2rem; 233 | border-radius: 5px; 234 | } 235 | 236 | .generated-image { 237 | object-fit: contain; 238 | padding-right: 20px; 239 | padding-top: 5px; 240 | padding-bottom: 30px; 241 | border-radius: 5px; 242 | } 243 | 244 | img { 245 | width: 50%; 246 | height: 50%; 247 | object-fit: contain; 248 | border-radius: 5px; 249 | } 250 | 251 | .model_select { 252 | position: absolute; 253 | top: 17%; 254 | left: 5%; 255 | transform: translate(-20%, -50%); 256 | max-width: 200px; 257 | padding: 10px; 258 | background-color: rgba(255, 255, 255, 0.73); 259 | font-weight: bold; 260 | border-radius: 5px; 261 | border: 1px solid #ccc; 262 | box-shadow: 0 0 10px rgba(30, 30, 30, 0.76); 263 | z-index: 1; 264 | } 265 | 266 | /* Popup form styles */ 267 | .popup { 268 | position: fixed; 269 | top: 0; 270 | left: 0; 271 | width: 100%; 272 | height: 100%; 273 | background: rgba(0, 0, 0, 0.5); 274 | display: flex; 275 | justify-content: center; 276 | align-items: center; 277 | z-index: 1000; 278 | } 279 | 280 | .popup-inner { 281 | background: white; 282 | padding: 20px; 283 | color: black; 284 | border-radius: 8px; 285 | width: 300px; 286 | box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); 287 | text-align: left; 288 | } 289 | 290 | .api-key-form label { 291 | display: block; 292 | margin-bottom: 10px; 293 | } 294 | 295 | .api-key-form input { 296 | width: calc(100% - 20px); 297 | padding: 5px; 298 | margin-bottom: 10px; 299 | } 300 | 301 | .api-key-form button { 302 | margin-right: 10px; 303 | } 304 | 305 | .cred { 306 | margin-bottom: 0.7rem; 307 | margin-left: 1.5rem; 308 | background-color: #4CAF50; 309 | border: none; 310 | color: white; 311 | padding: 5px; 312 | display: flex; 313 | cursor: pointer; 314 | border-radius: 5px; 315 | align-items: center; 316 | justify-content: center; 317 | transition: background-color 0.3s; 318 | } 319 | 320 | .cred:hover { 321 | background-color: #45a049; 322 | } 323 | 324 | .api-submit { 325 | background-color: black; 326 | color: white; 327 | padding: 10px; 328 | border: 0; 329 | margin-top: 1rem; 330 | border-radius: 5px; 331 | } 332 | 333 | .api-submit:hover { 334 | background-color: #333; 335 | } 336 | 337 | .api-close { 338 | background-color: black; 339 | color: white; 340 | padding: 10px; 341 | border: 0; 342 | margin-top: 1rem; 343 | border-radius: 5px; 344 | } 345 | 346 | .api-close:hover { 347 | background-color: #333; 348 | } 349 | 350 | -------------------------------------------------------------------------------- /AI_Chatbot/src/App.jsx: -------------------------------------------------------------------------------- 1 | import { useState, useEffect, useRef } from "react"; 2 | import axios from "axios"; 3 | import pdfToText from "react-pdftotext"; 4 | import { IoMdMicOff, IoMdSend } from "react-icons/io"; 5 | import ReactMarkdown from "react-markdown"; 6 | import { BsFillRecord2Fill } from "react-icons/bs"; 7 | import MonsterApiClient from "monsterapi"; 8 | import "./App.css"; 9 | import { MdAttachFile } from "react-icons/md"; 10 | 11 | const audioBlobToBase64 = (blob) => { 12 | return new Promise((resolve, reject) => { 13 | const reader = new FileReader(); 14 | reader.onloadend = () => { 15 | const arrayBuffer = reader.result; 16 | const base64Audio = btoa( 17 | new Uint8Array(arrayBuffer).reduce( 18 | (data, byte) => data + String.fromCharCode(byte), 19 | "" 20 | ) 21 | ); 22 | resolve(base64Audio); 23 | }; 24 | reader.onerror = reject; 25 | reader.readAsArrayBuffer(blob); 26 | }); 27 | }; 28 | 29 | const AVAILABLE_MODELS = [ 30 | 'models/gemini-1.5-flash','models/gemini-1.0-pro', 'models/gemini-1.0-pro-001', 'models/gemini-1.0-pro-latest', 31 | 'models/gemini-1.0-pro-vision-latest', 'models/gemini-1.5-flash-001', 32 | 'models/gemini-1.5-flash-latest', 'models/gemini-1.5-pro', 'models/gemini-1.5-pro-001', 33 | 'models/gemini-1.5-pro-latest', 'models/gemini-pro', 'models/gemini-pro-vision' 34 | ]; 35 | 36 | function App() { 37 | const [messages, setMessages] = useState([]); 38 | const [input, setInput] = useState(""); 39 | const [recording, setRecording] = useState(false); 40 | const [mediaRecorder, setMediaRecorder] = useState(null); 41 | const [transcription, setTranscription] = useState(""); 42 | const [pdfText, setPdfText] = useState(""); 43 | const [selectedModel, setSelectedModel] = useState(AVAILABLE_MODELS[0]); 44 | const [generatedImage, setGeneratedImage] = useState(null); 45 | const [file, setFile] = useState(null); 46 | const [apiKeyFormVisible, setApiKeyFormVisible] = useState(false); 47 | const [geminiApiKey, setGeminiApiKey] = useState(""); 48 | const [monsterApiKey, setMonsterApiKey] = useState(""); 49 | const [googleApiKey, setGoogleApiKey] = useState(""); 50 | const msgRef = useRef(null); 51 | const pdfFileInputRef = useRef(null); 52 | const imageFileInputRef = useRef(null); 53 | 54 | useEffect(() => { 55 | return () => { 56 | if (mediaRecorder) { 57 | mediaRecorder.stream.getTracks().forEach((track) => track.stop()); 58 | } 59 | }; 60 | }, [mediaRecorder]); 61 | 62 | useEffect(() => { 63 | msgRef.current?.scrollIntoView({ behavior: "smooth", block: "end" }); 64 | }, [messages]); 65 | 66 | const handleInputChange = (e) => { 67 | setInput(e.target.value); 68 | }; 69 | 70 | const handleModelChange = (e) => { 71 | setSelectedModel(e.target.value); 72 | }; 73 | 74 | const handleSendMessage = async () => { 75 | if (input.trim() === "" && !file) return; 76 | 77 | const userMessage = { from: "user", text: input, image: file ? URL.createObjectURL(file) : null }; 78 | setMessages([...messages, userMessage]); 79 | setInput(""); 80 | setFile(null); 81 | 82 | if (input.toLowerCase().startsWith("generate")) { 83 | await handleGenerateImage(input); 84 | return; 85 | } 86 | 87 | const formData = new FormData(); 88 | formData.append("message", input); 89 | formData.append("context", pdfText); 90 | formData.append("model", selectedModel); 91 | formData.append("geminiApiKey", geminiApiKey); 92 | if (file) { 93 | formData.append("file", file); 94 | } 95 | 96 | try { 97 | const response = await fetch("https://botserver.applikuapp.com/chat", { 98 | method: "POST", 99 | body: formData, 100 | }); 101 | const data = await response.json(); 102 | if (!response.ok) { 103 | throw new Error(data.error || "An error occurred"); 104 | } 105 | const botMessage = { from: "bot", text: data.response, image: data.image_url }; 106 | setMessages((prevMessages) => [...prevMessages, botMessage]); 107 | speakText(data.response); 108 | } catch (error) { 109 | console.error(error); 110 | alert("An error occurred. Please try again."); 111 | } 112 | }; 113 | 114 | const handleGenerateImage = async (prompt) => { 115 | const model = "txt2img"; 116 | const input = { prompt: prompt.replace("generate", "").trim() }; 117 | const monsterClient = new MonsterApiClient(monsterApiKey); 118 | 119 | console.log("Generating image with prompt:", input); 120 | 121 | try { 122 | const response = await monsterClient.generate(model, input); 123 | console.log("MonsterAPI response:", response); 124 | 125 | if (response.output && response.output.length > 0) { 126 | const imageUrl = response.output[0]; 127 | setGeneratedImage(imageUrl); 128 | const botMessage = { from: "bot", text: `![Generated Image](${imageUrl})` }; 129 | setMessages((prevMessages) => [...prevMessages, botMessage]); 130 | speakText("Here is the generated image."); 131 | } else { 132 | console.error("Image generation failed:", response); 133 | const botMessage = { from: "bot", text: "Failed to generate image. Please try again." }; 134 | setMessages((prevMessages) => [...prevMessages, botMessage]); 135 | speakText("Failed to generate image. Please try again."); 136 | } 137 | } catch (error) { 138 | console.error("Error generating image:", error); 139 | alert("Failed to generate image. Please try again."); 140 | } 141 | }; 142 | 143 | const handleKeyDown = (e) => { 144 | if (e.key === "Enter") { 145 | handleSendMessage(); 146 | } 147 | }; 148 | 149 | const startRecording = async () => { 150 | try { 151 | const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); 152 | const recorder = new MediaRecorder(stream); 153 | recorder.start(); 154 | console.log("Recording started"); 155 | 156 | recorder.addEventListener("dataavailable", async (event) => { 157 | const audioBlob = event.data; 158 | console.log("Audio blob:", audioBlob); 159 | 160 | const base64Audio = await audioBlobToBase64(audioBlob); 161 | console.log("Base64 audio:", base64Audio); 162 | 163 | console.log("Audio blob size:", audioBlob.size); 164 | console.log("Audio blob type:", audioBlob.type); 165 | 166 | try { 167 | const response = await axios.post( 168 | `https://speech.googleapis.com/v1/speech:recognize?key=${googleApiKey}`, 169 | { 170 | config: { 171 | encoding: "WEBM_OPUS", 172 | sampleRateHertz: 48000, 173 | languageCode: "en-US", 174 | }, 175 | audio: { 176 | content: base64Audio, 177 | }, 178 | } 179 | ); 180 | 181 | console.log("Google Speech-to-Text API response:", response.data); 182 | 183 | if (response.data.results && response.data.results.length > 0) { 184 | const transcript = response.data.results[0].alternatives[0].transcript; 185 | console.log("Transcript:", transcript); 186 | setTranscription(transcript); 187 | setInput(transcript); 188 | } else { 189 | setTranscription("No transcription available"); 190 | console.log("No transcription available"); 191 | } 192 | } catch (error) { 193 | console.error("Error with Google Speech-to-Text API:", error.response?.data || error.message); 194 | } 195 | }); 196 | 197 | setRecording(true); 198 | setMediaRecorder(recorder); 199 | } catch (error) { 200 | console.error("Error getting user media:", error); 201 | } 202 | }; 203 | 204 | const stopRecording = () => { 205 | if (mediaRecorder) { 206 | mediaRecorder.stop(); 207 | console.log("Recording stopped"); 208 | setRecording(false); 209 | } 210 | }; 211 | 212 | const extractText = async (event) => { 213 | const file = event.target.files[0]; 214 | try { 215 | const text = await pdfToText(file); 216 | setPdfText(text); 217 | alert("Text extracted successfully"); 218 | pdfFileInputRef.current.value = ""; 219 | } catch (error) { 220 | console.error("Failed to extract text from PDF", error); 221 | } 222 | }; 223 | 224 | const clearPdfText = () => { 225 | setPdfText(""); 226 | pdfFileInputRef.current.value = ""; 227 | }; 228 | 229 | const speakText = (text) => { 230 | if ('speechSynthesis' in window) { 231 | const utterance = new SpeechSynthesisUtterance(text); 232 | utterance.lang = 'en-US'; 233 | window.speechSynthesis.speak(utterance); 234 | } else { 235 | console.error("Web Speech API is not supported in this browser."); 236 | } 237 | }; 238 | 239 | const handleSubmitApiKeys = (e) => { 240 | e.preventDefault(); 241 | setApiKeyFormVisible(false); 242 | }; 243 | 244 | return ( 245 |
246 |
247 |
248 |
249 |

AI Chat Bot

250 |
251 |
252 | 259 |
260 | {messages.map((msg, index) => ( 261 |
262 |

263 | {msg.text} 264 | {msg.from === 'user' && msg.image && attached} 265 |

266 |
267 | ))} 268 |
269 |
270 | 271 | 274 | setFile(e.target.files[0])} 280 | /> 281 |
282 | 290 |
291 | 297 |
298 | 301 |
302 |
303 |
304 |
305 |
306 |
307 |

PDF Context Loader

308 |
309 | 316 |
317 |

Extracted Text

318 |
{pdfText}
319 |
320 | 323 |
324 |
325 | {apiKeyFormVisible && ( 326 |
327 |
328 |
329 | 337 | 345 | 353 | 354 | 355 |
356 |
357 |
358 | )} 359 |
360 | ); 361 | } 362 | 363 | export default App; 364 | --------------------------------------------------------------------------------