├── .eslintrc.cjs ├── .github └── workflows │ └── deployment.yml ├── .gitignore ├── LICENSE ├── README.md ├── index.html ├── package-lock.json ├── package.json ├── postcss.config.js ├── src ├── App.css ├── App.jsx ├── components │ └── ChatWithGemini.jsx ├── hooks │ └── useGemini.jsx ├── icons │ └── google.svg ├── index.css ├── main.jsx ├── service │ └── gemini.service.js └── utils │ └── config.js ├── tailwind.config.js └── vite.config.js /.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-refresh/only-export-components': [ 16 | 'warn', 17 | { allowConstantExport: true }, 18 | ], 19 | }, 20 | } 21 | -------------------------------------------------------------------------------- /.github/workflows/deployment.yml: -------------------------------------------------------------------------------- 1 | # Simple workflow for deploying static content to GitHub Pages 2 | name: Deploy static content to Pages 3 | 4 | on: 5 | # Runs on pushes targeting the default branch 6 | push: 7 | branches: ['main'] 8 | 9 | # Allows you to run this workflow manually from the Actions tab 10 | workflow_dispatch: 11 | 12 | # Sets the GITHUB_TOKEN permissions to allow deployment to GitHub Pages 13 | permissions: 14 | contents: read 15 | pages: write 16 | id-token: write 17 | 18 | # Allow one concurrent deployment 19 | concurrency: 20 | group: 'pages' 21 | cancel-in-progress: true 22 | 23 | jobs: 24 | # Single deploy job since we're just deploying 25 | deploy: 26 | environment: 27 | name: github-pages 28 | url: ${{ steps.deployment.outputs.page_url }} 29 | runs-on: ubuntu-latest 30 | steps: 31 | - name: Checkout 32 | uses: actions/checkout@v4 33 | - name: Set up Node 34 | uses: actions/setup-node@v3 35 | with: 36 | node-version: 21.2.0 37 | cache: 'npm' 38 | - name: Install dependencies 39 | run: npm install 40 | - name: Build 41 | run: npm run build 42 | env: 43 | VITE_APP_BOT_API_KEY: ${{ secrets.VITE_APP_BOT_API_KEY }} 44 | - name: Setup Pages 45 | uses: actions/configure-pages@v3 46 | - name: Upload artifact 47 | uses: actions/upload-pages-artifact@v2 48 | with: 49 | # Upload dist repository 50 | path: './dist' 51 | - name: Deploy to GitHub Pages 52 | id: deployment 53 | uses: actions/deploy-pages@v2 -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Sai Barath 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 | # Gemini Bot 3 | 4 | ## Description 5 | 6 | This project is an AI chatbot that uses the Gemini API from Google. It's designed for educational purposes, providing a practical example of how to implement a chat bot using Gemini API. 7 | 8 | The chatbot has the following features: 9 | 10 | - **Multi-Conversation**: The chatbot can handle multiple conversations at once. It initializes the chat by calling `startChat()`, and then uses `sendMessage()` to send new user messages. These messages, along with the chatbot's responses, are appended to the chat history. 11 | 12 | - **User and Model Roles**: The chatbot uses two roles: 'user' and 'model'. The 'user' role provides the prompts, while the 'model' role provides the responses. 13 | 14 | - **Streaming**: The chatbot uses streaming for faster interactions. Instead of waiting for the model to complete the entire generation process, the chatbot can handle partial results for quicker responses. 15 | 16 | ## Screenshots 17 | 18 | ![Screenshot 2023-12-31 at 6 41 27 PM](https://github.com/SaiBarathR/gemini-bot-react/assets/58382813/fe6aa8e8-40bb-468a-bb21-2a8697c195ba) 19 | 20 | 21 | ## Dependencies 22 | 23 | This project uses the following libraries: 24 | 25 | - React 26 | - Vite 27 | - Tailwind 28 | - Chakra UI 29 | - React Markdown 30 | - @google/generative-ai 31 | 32 | ## API Key 33 | 34 | To run this project, you'll need an API key from Google. You can get one for free at [Google AI](https://ai.google.dev/). The free API key comes with some limitations: 35 | 36 | - Rate Limit: The free API key allows for up to 60 queries per minute. 37 | - Data Usage: The input/output data is used to improve Google's products. 38 | 39 | ## Usage 40 | 41 | To use this project: 42 | 43 | 1. Clone the repository. 44 | 2. Install the dependencies. 45 | 3. Insert your API key. 46 | 4. Run the project. 47 | 48 | ## License 49 | 50 | This project is free to use for educational purposes. 51 | 52 | ## Links 53 | 54 | - [Google AI](https://ai.google.dev/) 55 | - [Google AI Web QuickStart](https://ai.google.dev/tutorials/web_quickstart) 56 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Gemini Bot 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gemini-bot-react", 3 | "private": true, 4 | "version": "0.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 | "@chakra-ui/icons": "^2.1.1", 14 | "@chakra-ui/react": "^2.8.2", 15 | "@emotion/react": "^11.11.1", 16 | "@emotion/styled": "^11.11.0", 17 | "@google/generative-ai": "^0.1.2", 18 | "framer-motion": "^10.16.16", 19 | "react": "^18.2.0", 20 | "react-dom": "^18.2.0", 21 | "react-markdown": "^9.0.1" 22 | }, 23 | "devDependencies": { 24 | "@types/react": "^18.2.43", 25 | "@types/react-dom": "^18.2.17", 26 | "@vitejs/plugin-react": "^4.2.1", 27 | "autoprefixer": "^10.4.16", 28 | "eslint": "^8.55.0", 29 | "eslint-plugin-react": "^7.33.2", 30 | "eslint-plugin-react-hooks": "^4.6.0", 31 | "eslint-plugin-react-refresh": "^0.4.5", 32 | "postcss": "^8.4.32", 33 | "tailwindcss": "^3.3.6", 34 | "vite": "^5.0.8" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | font-family: 'Roboto', sans-serif; 3 | height: 100vh; 4 | width: 100%; 5 | max-height: none !important; 6 | display: flex; 7 | flex-direction: column; 8 | } 9 | 10 | /* ScrollBar CSS */ 11 | 12 | ::-webkit-scrollbar-track { 13 | background-color: rgba(237, 240, 242, 0.5); 14 | border-radius: 5px; 15 | } 16 | 17 | ::-webkit-scrollbar { 18 | width: 4px; 19 | height: 8px; 20 | background-color: rgb(240, 240, 240); 21 | border-radius: 5px; 22 | } 23 | 24 | ::-webkit-scrollbar-thumb { 25 | background-color: rgb(190, 190, 190); 26 | border-radius: 5px; 27 | } 28 | 29 | /* Loader */ 30 | 31 | .dot { 32 | width: 8px; 33 | height: 8px; 34 | border-radius: 50%; 35 | display: inline-block; 36 | animation: dot-keyframes 1.4s infinite; 37 | } 38 | 39 | .dot:nth-child(1) { 40 | animation-delay: 0.2s; 41 | } 42 | 43 | .dot:nth-child(2) { 44 | animation-delay: 0.4s; 45 | } 46 | 47 | .dot:nth-child(3) { 48 | animation-delay: 0.6s; 49 | } 50 | 51 | @keyframes dot-keyframes { 52 | 53 | 0%, 54 | 80%, 55 | 100% { 56 | transform: scale(0); 57 | } 58 | 59 | 40% { 60 | transform: scale(1); 61 | } 62 | } -------------------------------------------------------------------------------- /src/App.jsx: -------------------------------------------------------------------------------- 1 | import ChatWithGemini from './components/ChatWithGemini' 2 | import { Container } from '@chakra-ui/react' 3 | import './App.css' 4 | 5 | function App() { 6 | 7 | return ( 8 | 9 | 10 | 11 | ) 12 | } 13 | 14 | export default App 15 | -------------------------------------------------------------------------------- /src/components/ChatWithGemini.jsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | import { useEffect, useRef, useState } from "react"; 3 | import { Input } from "@chakra-ui/react"; 4 | import { InputGroup, Box, InputRightElement, Button } from "@chakra-ui/react" 5 | import { motion } from 'framer-motion' 6 | import { Text } from '@chakra-ui/react' 7 | import { Textarea } from "@chakra-ui/react" 8 | import { DeleteIcon } from '@chakra-ui/icons' 9 | import { ArrowForwardIcon } from '@chakra-ui/icons' 10 | import ReactMarkdown from 'react-markdown' 11 | import GeminiService from "../service/gemini.service"; 12 | import useGemini from "../hooks/useGemini"; 13 | import PropTypes from 'prop-types' 14 | 15 | const ChatWithGemini = () => { 16 | 17 | const { messages, loading, sendMessages, updateMessage } = useGemini() 18 | const [input, setInput] = useState(''); 19 | 20 | const AlwaysScrollToBottom = () => { 21 | const elementRef = useRef(); 22 | useEffect(() => elementRef.current.scrollIntoView({ 23 | behavior: 'smooth', block: 'start', inline: 'nearest', 24 | })); 25 | return
; 26 | }; 27 | 28 | const handleSend = async () => { 29 | if (!input) return 30 | setInput('') 31 | updateMessage([...messages, { "role": "user", "parts": [{ "text": input }] }]) 32 | sendMessages({ message: input, history: messages }) 33 | } 34 | 35 | return ( 36 | <> 37 | 38 | 39 | {messages.length > 0 ? messages.map((message, index) => ) : 40 | 41 | } 42 | 43 | 44 | 45 | 46 | 47 |