In today's digital age, chatbots have become an indispensable tool for businesses to engage with their customers and automate various tasks. With the advancement of natural language processing (NLP) technologies, it's now easier than ever to create your chatbot using powerful APIs like Gemini.
Gemini is an open-source NLP API that provides a robust set of features for building intelligent chatbot experiences. In this article, we'll guide you through the step-by-step process of creating a custom chatbot using Gemini and Django, a popular Python web framework.
Prerequisites
Before diving into the development process, you need to have a basic understanding of Python and some experience with web development. Additionally, it is recommended to have a development environment set up, including Python, pip, and a text editor or IDE.
Step 1: Install Django & Google Generativeai
The first step in building a chatbot with Django is to install the framework and install Google Generativeai. You can do this by using the pip package manager with the following command:
pip install Django
pip install google-generativeai
Step 2: Create a Django Project
Once you have installed Django & Google Generativeai, you can create a new project by using the following command:
django-admin startproject chatbot
This will create a new directory called chatbot
that contains the basic structure of your Django project.
Step 3: Create a Django App
A Django project can consist of multiple apps, each of which can handle a specific functionality of the website. To create a new app, navigate to the project directory and run the following command:
python manage.py startapp chat_app
This will create a new directory with the same name as your app, containing all the necessary files to run a Django app. Your structure will look like this:
├── chat_app
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── chatbot
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-310.pyc
│ │ └── settings.cpython-310.pyc
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── manage.py
Step 4: Add your app to the project's settings
Your project directory will have a settings.py
file, open it and mention the app like this:
# Application definition
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"chat_app",
]
LOGIN_URL = "/admin/login/"
In this Django application, the INSTALLED_APPS
variable defines the list of Django applications that are installed and available for use in the project. Each application listed here can contain models, views, templates, and other components specific to its functionality.
Additionally, the LOGIN_URL
setting specifies the URL where users should be redirected if they are not logged in and try to access a view that requires authentication. In this case, it's set to "/admin/login/"
, meaning unauthorized users will be redirected to the admin login page if they attempt to access a protected view.
Step 5: Define Models
Models are the backbone of a Django website, representing the data that will be stored in the database. To define models, open the models.py
file in your app directory and add the following code:
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class ChatBot(models.Model):
user = models.ForeignKey(
User, on_delete=models.CASCADE, related_name="GeminiUser", null=True
)
text_input = models.CharField(max_length=500)
gemini_output = models.TextField(null=True, blank=True)
date = models.DateTimeField(auto_now_add=True, blank=True, null=True)
def __str__(self):
return self.text_input
Here I have created only 4 fields, which you can add as per your requirement.
Step 6: Migrate the Database
Once you have defined your models, you need to create the database tables to store the data. You can do this by running the following command:
python manage.py makemigrations
python manage.py migrate
You should also create a superuser because we will only allow logged-in users to do this.
python manage.py createsuperuser
Step 7: Create Views
Views handle the logic of the chatbot and render the template, which is the HTML file that displays the content to the user. To create views, open the views.py
file in your app directory and add the following code:
from django.shortcuts import render, reverse
from django.contrib.auth.decorators import login_required
from .models import ChatBot
from django.http import HttpResponseRedirect, JsonResponse
import google.generativeai as genai
# Create your views here.
# add here to your generated API key
genai.configure(api_key="YourAPI-Key")
@login_required
def ask_question(request):
if request.method == "POST":
text = request.POST.get("text")
model = genai.GenerativeModel("gemini-pro")
chat = model.start_chat()
response = chat.send_message(text)
user = request.user
ChatBot.objects.create(text_input=text, gemini_output=response.text, user=user)
# Extract necessary data from response
response_data = {
"text": response.text, # Assuming response.text contains the relevant response data
# Add other relevant data from response if needed
}
return JsonResponse({"data": response_data})
else:
return HttpResponseRedirect(
reverse("chat")
) # Redirect to chat page for GET requests
@login_required
def chat(request):
user = request.user
chats = ChatBot.objects.filter(user=user)
return render(request, "chat_bot.html", {"chats": chats})
Here is the summary of this code:
-
Imports: The code imports necessary modules from Django, including shortcuts for rendering templates and reversing URLs, decorators for handling user authentication, and the
ChatBot
model representing chat interactions. Additionally, it imports thegenai
module to access the Google Generative AI API. -
Google Generative AI Configuration: The API key required to access the Google Generative AI API is configured using the
genai
module. Click here to generate your API key. -
ask_question
View: This view is decorated with@login_required
, ensuring that only authenticated users can access it. It handles both GET and POST requests. Upon receiving a POST request, the view extracts the user's input text, interacts with the Generative AI model to obtain a response, saves the input, output, and user information in the database using theChatBot
model, and returns the response data as a JSON object. In the case of a GET request, the user is redirected to the chat page. -
chat
View: Similarly decorated with@login_required
, this view retrieves all previous chat interactions associated with the current authenticated user from the database using theChatBot
model. It then renders these interactions within a template named "chat_bot.html" for the user to view. -
Template: The "chat_bot.html" template is responsible for presenting the user's past interactions with the chatbot in a visually intuitive and user-friendly manner, likely displaying the user's input along with the corresponding responses from the Generative AI model.
Step 8: Create Templates
We will create a template. To create this, we will create a folder named templates
inside the directory of our chat_app
. We will name it chat_bot.html
which we have also mentioned in our views.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ChatBot</title>
<!-- Font Awesome -->
<link
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"
rel="stylesheet"
/>
<!-- Google Fonts -->
<link
href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
rel="stylesheet"
/>
<!-- MDB -->
<link
href="https://cdnjs.cloudflare.com/ajax/libs/mdb-ui-kit/7.1.0/mdb.min.css"
rel="stylesheet"
/>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.4.0/styles/default.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.4.0/highlight.min.js"></script>
</head>
<body>
<style>
body {
background-image: url("https://espere.in/static/images/chat.png");
background-position: center center;
background-repeat: no-repeat;
background-attachment: fixed;
background-size: cover;
background-color: rgba(161, 161, 161, 0.108);
}
#chat4 .form-control {
border-color: transparent;
}
#chat4 .form-control:focus {
border-color: transparent;
box-shadow: inset 0px 0px 0px 1px transparent;
}
.divider:after,
.divider:before {
content: "";
flex: 1;
height: 1px;
background: #eee;
}
#scroll::-webkit-scrollbar{
background-color: rgba(0, 0, 0, 0.108); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(5px);
width: 0px;
height: 0px;
color: #eee;
}
pre::-webkit-scrollbar{
background-color: rgba(0, 0, 0, 0.108); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(5px);
width: 0px;
height: 0px;
}
div {
position: relative; /* Set position to relative for the container */
}
pre {
overflow-x: scroll; /* Enable horizontal scrolling */
width: 68vw;
/* white-space: pre-wrap; Preserve line breaks */
}
pre button {
position: absolute;
top: 1px;
left: calc(68vw - 2rem); /* Adjust the position of the button */
font-size: 0.9rem;
padding: 0.5rem; /* Changed to a positive value */
background-color: rgb(50, 50, 50);
border-radius: 50px;
border: none;
}
.form{
width: 100%;
}
#questionInput{
background-color: rgba(253, 253, 253, 0.532);
-webkit-backdrop-filter: blur(8px);
backdrop-filter: blur(5px);
border: 2px solid rgb(255, 255, 255);
border-radius: 45px;
height: 40px;
}
.tooltip-inner {
background-color: rgb(100, 100, 100);
border-radius: 2px;
position: relative;
padding: 2px 10px;
font-size: small;
}
.tooltip-inner::before {
content: "";
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%);
border-width: 6px;
border-style: solid;
border-color: transparent transparent rgb(100, 100, 100) transparent;
}
#scroll {
margin: 4px, 4px;
padding: 4px;
width: 100%;
height: 57.0vh;
overflow-x: auto;
/* overflow-y: auto; */
text-align: justify;
/* border: 1px solid rgb(14, 119, 163); */
border-radius: 3px;
}
#scroll::-webkit-scrollbar {
width: 5px;
height: 0px;
}
/* Track */
#scroll::-webkit-scrollbar-track {
box-shadow: inset 0 0 7px rgb(219, 219, 219);
border-radius: 10px;
}
/* Handle */
#scroll::-webkit-scrollbar-track {
box-shadow: inset 0 0 7px rgb(255, 255, 255);
border-radius: 10px;
}
/* Handle */
#scroll::-webkit-scrollbar-thumb {
background: rgb(215, 215, 215);
border-radius: 10px;
}
/* Handle on hover */
#scroll::-webkit-scrollbar-thumb:hover {
background: rgb(159, 159, 159);
}
pre {
/* background-color: #dcdcdc; */
padding: 1em;
width: 100%;
overflow-x: auto;
border-radius: 5px;
border: 1px solid #ddd;
}
code {
font-family: 'Courier New', Courier, monospace;
font-size: 14px;
}
.loader-container {
display: flex;
justify-content: center;
align-items: center;
margin-top: 5px;
margin-bottom: 10px;
}
.loader {
width: 120px;
height: 20px;
-webkit-mask: linear-gradient(90deg,#000 70%,#0000 0) left/20% 100%;
background:
linear-gradient(#000 0 0) left -25% top 0 /20% 100% no-repeat
rgb(226, 229, 205);
animation: l7 1s infinite steps(6);
}
@keyframes l7 {
100% {background-position: right -25% top 0}
}00% {background-position: 0 0}
}
</style>
<div class="container">
<div class="row">
<div style="border-radius: 5px; background-color: rgba(161, 161, 161, 0.108); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(5px);" class="modal-content con mt-4 mb-4">
<div style="background-color: rgba(161, 161, 161, 0.108); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(5px); border-radius: 5px 5px 0px 0px;" class="modal-header text-white shadow-5">
<div class="my-3">
<a class="text-dark" href="javascript:history.back()"><i type="button" data-mdb-dismiss="modal" style="font-size: 18px;" class="fas fa-arrow-left"></i></a>
<img class="ms-2" src="https://espere.in/static/images/newlogo.png" alt="Header Image" style="border-radius: 50%; max-height: 35px; max-width: 50px;">
<span class="ms-1 text-dark">ChatBot</span>
</div>
<a data-mdb-placement="bottom" data-mdb-toggle="tooltip" title="Reload" class="text-dark" href="{% url 'chat' %}"><i type="button" data-mdb-dismiss="modal" style="font-size: 18px;" class="fas fa-arrows-rotate"></i></a>
</div>
<div style="background-color: rgba(161, 161, 161, 0.108); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(5px);" class="modal-body">
<div style="background-color: transparent;" id="chat4">
<div id="scroll" class="card-body my-3" data-mdb-perfect-scrollbar="true"
style="position: relative; height: 66vh">
{% if chats %}
{% for chat in chats %}
<div id="chatCard">
<div class="d-flex flex-row justify-content-end mb-3">
<div>
<div style="background-color: #1b1b1b8e; font-size: smaller; border-radius: 20px 0px 20px 20px;" class="small p-2 me-2 mb-1 text-white ms-auto">{{ chat.text_input }}</div>
</div>
<img class="rounded-circle mb-1" src="https://espere.in/static/images/profile.webp"
alt="avatar 1" style="width: 40px; height: 100%;">
</div>
<div id="response_data" class="d-flex flex-row justify-content-start mb-3">
<img src="https://espere.in/static/images/newlogo.png"
alt="avatar 1" style="width: 40px; height: 100%;">
<div>
<div id="chatArea" class="small p-2 ms-2 mb-1 me-auto text-dark" style="background-color: #ffffffb8; font-size: smaller; border-radius: 0px 20px 20px 20px;">{{ chat.gemini_output | safe }}</div>
</div>
</div>
</div>
{% endfor %}
{% endif %}
</div>
<div class="loader-container">
<div style="color: #242424b1;" class="d-flex align-items-center me-3" id="loading">
</div>
</div>
<div class="card-footer text-muted d-flex justify-content-start align-items-center p-3">
<img class="rounded-circle" src="https://espere.in/static/images/profile.webp"
alt="avatar 3" style="width: 40px; height: 100%;">
<form class="form" onsubmit="askQuestion(event)">
<input class="form-control ms-2" type="text" id="userText" name="text" placeholder="Ask your question">
</form>
<span id="submitBtn" style="background-color: rgba(253, 253, 253, 0.532); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(5px)" type="submit" class="ms-3 link-danger btn btn-floating" href=""><i class="fas fa-paper-plane"></i></span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- MDB -->
<script
type="text/javascript"
src="https://cdnjs.cloudflare.com/ajax/libs/mdb-ui-kit/7.1.0/mdb.umd.min.js"
></script>
<!-- jquery -->
<script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/markdown-it/dist/markdown-it.min.js"></script>
<script>
let chatCard = document.querySelector('#scroll');
chatCard.scrollTop = chatCard.scrollHeight;
document.addEventListener('DOMContentLoaded', function(){
document.querySelector('#submitBtn').addEventListener('click', () => chat_ajax());
});
function myFunction() {
document.getElementById("userText").disabled = true;
document.querySelector('#userText').setAttribute('placeholder', 'Please wait, your result will come soon...');
}
function enableUserText() {
// Enable the input field
document.getElementById("userText").disabled = false;
document.querySelector('#userText').setAttribute('placeholder', 'Ask your question');
}
function chat_ajax() {
const md = new markdownit({ html: true });
let text = document.querySelector('#userText').value;
let html = md.renderInline(text);
let chatCard = document.querySelector('#scroll');
// Append user's message to chat card
chatCard.innerHTML += `
<div class="d-flex flex-row justify-content-end mb-3">
<div>
<div style="background-color: #1b1b1b8e; font-size: smaller; border-radius: 20px 0px 20px 20px;" class="small p-2 me-2 mb-1 text-white ms-auto">${text}</div>
</div>
<img class="rounded-circle mb-1" src="https://espere.in/static/images/profile.webp" alt="avatar 1" style="width: 40px; height: 100%;">
</div>
`;
chatCard.scrollTop = chatCard.scrollHeight;
console.log(text);
document.querySelector('#userText').value = null;
var loading = document.querySelector('#loading');
myFunction();
loading.innerHTML = `
<div class="loader">
</div>
`;
chatCard.scrollTop = chatCard.scrollHeight;
$.ajax({
type: 'POST',
url: '/ask_question/',
data: {
'text': text,
csrfmiddlewaretoken: '{{ csrf_token }}',
},
success: function(res) {
var response = md.render(res.data.text); // Render Markdown content
var chatCard = document.getElementById('scroll');
var typingSpeed = 15; // Set the typing speed in milliseconds
// Create response_data div
var responseDataDiv = document.createElement('div');
responseDataDiv.id = 'response_data';
responseDataDiv.classList.add('d-flex', 'flex-row', 'justify-content-start', 'mb-3');
chatCard.appendChild(responseDataDiv);
// Create avatar image
var avatarImg = document.createElement('img');
avatarImg.src = "https://espere.in/static/images/newlogo.png";
avatarImg.alt = "avatar 1";
avatarImg.style.width = '40px';
avatarImg.style.height = '100%';
responseDataDiv.appendChild(avatarImg);
// Create chatArea div
var chatAreaDiv = document.createElement('div');
chatAreaDiv.id = 'chatArea';
chatAreaDiv.classList.add('small', 'p-2', 'ms-2', 'mb-1', 'me-auto', 'text-dark');
chatAreaDiv.style.backgroundColor = '#ffffffb8';
chatAreaDiv.style.fontSize = 'smaller';
chatAreaDiv.style.borderRadius = '0px 20px 20px 20px';
chatAreaDiv.innerHTML = response;
responseDataDiv.appendChild(chatAreaDiv);
// chatAreaDiv.innerHTML += response
loading.innerHTML = '';
chatCard.scrollTop = chatCard.scrollHeight;
enableUserText();
},
error: function() {
console.log("There was an error!");
}
});
}
</script>
</body>
</html>
You can adjust it as per your requirement, I have designed it just basic, I am not good at JavaScript, but you can do it as per your requirement.
Step 9: Configure URLs
URLs define the mapping between the web address and the view that should be displayed. To configure URLs, you have to create a file named urls.py
in chat_app
and add your URLs inside it.
from django.urls import path
from . import views
urlpatterns = [
path("", views.chat, name="chat"),
path("ask_question/", views.ask_question, name="ask_question"),
]
You have to include this urls file in your base urls file which you will find in your project's directory.
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path("admin/", admin.site.urls),
path("", include("chat_app.urls")), # include this
]
This is the structure of the entire project:
├── chat_app
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-310.pyc
│ │ ├── admin.cpython-310.pyc
│ │ ├── apps.cpython-310.pyc
│ │ ├── models.cpython-310.pyc
│ │ ├── urls.cpython-310.pyc
│ │ └── views.cpython-310.pyc
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ ├── __init__.py
│ │ └── __pycache__
│ │ ├── 0001_initial.cpython-310.pyc
│ │ └── __init__.cpython-310.pyc
│ ├── models.py
│ ├── templates
│ │ ├── chat_bot.html
│ │ └── chat_bot1.html
│ ├── tests.py
│ ├── urls.py
│ └── views.py
├── chatbot
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-310.pyc
│ │ ├── settings.cpython-310.pyc
│ │ ├── urls.cpython-310.pyc
│ │ └── wsgi.cpython-310.pyc
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── db.sqlite3
└── manage.py
Step 10: Run the Development Server
Finally, you can run the development server by running the following command in your terminal:
python manage.py runserver
Once the server is running, you can visit "http://127.0.0.1:8000/" in your web browser to view your chatbot application. You can make changes to the code and the changes will be automatically reflected on the website when you refresh the page.
Conclusion
In conclusion, developing your chatbot using the Gemini API in Django can be an exciting and rewarding endeavour. By leveraging the power of generative AI technology provided by the Gemini API, you can create a conversational interface that interacts with users naturally and intelligently.
Throughout this article, we have explored the process of integrating the Gemini API into a Django application to build a chatbot. We started by setting up the necessary environment and configuring the Gemini API with your API key. Then, we implemented views in Django to handle user input, interact with the Gemini AI model, and store chat interactions in the database.
By following the steps outlined in this article, you can create a robust chatbot application that offers users a seamless conversational experience. Furthermore, you have the flexibility to customize and expand the functionality of your chatbot to suit your specific requirements and preferences.
Overall, building a chatbot using the Gemini API in Django opens up a world of possibilities for enhancing user engagement, automating tasks, and providing personalized experiences. With the right approach and creativity, you can develop a sophisticated chatbot that adds value to your Django application and delights your users.