├── 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 |
4 |
5 |
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 |
5 |
6 |
7 |
8 |
9 |
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 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
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: `` };
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 &&
}
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 |
358 | )}
359 |
360 | );
361 | }
362 |
363 | export default App;
364 |
--------------------------------------------------------------------------------