Google AI Gemini API: A Complete Example of a Python Flask ChatBot
We explore the Google AI Gemini API. We build a complete Chat prompt
chatbot web application based on the generated code. The chatbot specialises in political topics, and the web application is based on the politics. And the web application is based on the Flask web framework.
Google AI Gemini API: A Complete Example of a Python Flask ChatBot |
I’m intrigued by how seemingly easy it is to use the
Google AI Gemini API
(Gemini API
from now on). This is the primary reason for this post.
I’d like to write a complete chatbot web application to test out the Gemini API
.
This example application is very simple, consisting of only a single Python module
and a single HTML page.
❶ Gemini API
provides comprehensive documentation to get us up and running. The following resources are particularly helpful:
🚀 And the Google AI Studio, where:
-
A new
Chat prompt
can be created and tested, and later use theGet code
button to export theChat prompt
as program code in a language thatGemini API
supports, which, in this case, is Python. -
An API key can be obtained using the
Get API key
button.
❷ Third-Party Packages: We will need to install the following packages
into the active virtual environment, venv
:
- google-generativeai: This is the Google AI Python SDK for the Gemini API, as per the documentation.
-
python-dotenv:
This package reads key-value pairs from a
.env
file and can set them as environment variables. -
markdown:
This package converts Markdown response text from the
Gemini API
into HTML for display. - flask: This is the web framework we’ll be using.
Here are the commands to install these packages on Ubuntu 22.10:
(venv) behai@hp-pavilion-15:~/pydev$ ./venv/bin/pip install google-generativeai
(venv) behai@hp-pavilion-15:~/pydev$ ./venv/bin/pip install python-dotenv
(venv) behai@hp-pavilion-15:~/pydev$ ./venv/bin/pip install markdown
(venv) behai@hp-pavilion-15:~/pydev$ ./venv/bin/pip install flask
❸ Example Code: This section provides the source code along with a brief explanation of key points.
⓵ As noted above, this example demonstrates a single module on one page. The directory structure is illustrated below:
/home/behai/pydev/
├── .env
├── gemini_flask_01.py
└── templates
└── gemini_flask_01.html
⓶ The environment file .env
is where we store the GEMINI_API_KEY
obtained using the Google AI Studio.
Content of .env:
GEMINI_API_KEY=<YOUR_API_KEY>
We don’t have to use this mechanism to set the GEMINI_API_KEY
environment variable. We can set it for each console session. To set the
GEMINI_API_KEY
environment variable, use the following command:
▶️Windows 10: set GEMINI_API_KEY=<YOUR_API_KEY>
▶️Ubuntu 22.10: export GEMINI_API_KEY="<YOUR_API_KEY>"
To verify that the environment variable GEMINI_API_KEY
has been set, use the following command:
▶️Windows 10: echo %GEMINI_API_KEY%
▶️Ubuntu 22.10: printenv GEMINI_API_KEY
⓷ This is the Python example application module:
Content of gemini_flask_01.py:
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
96
import os
from dotenv import load_dotenv
import google.generativeai as genai
import flask
from flask import (
request,
render_template,
make_response,
)
import markdown
# Load the GEMINI_API_KEY from the .env file.
load_dotenv(os.path.join(os.getcwd(), '.env'))
genai.configure(api_key=os.environ["GEMINI_API_KEY"])
# Create the model
# See https://ai.google.dev/api/python/google/generativeai/GenerativeModel
generation_config = {
"temperature": 1,
"top_p": 0.95,
"top_k": 64,
"max_output_tokens": 8192,
"response_mime_type": "text/plain",
}
safety_settings = [
{
"category": "HARM_CATEGORY_HARASSMENT",
"threshold": "BLOCK_MEDIUM_AND_ABOVE",
},
{
"category": "HARM_CATEGORY_HATE_SPEECH",
"threshold": "BLOCK_MEDIUM_AND_ABOVE",
},
{
"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
"threshold": "BLOCK_MEDIUM_AND_ABOVE",
},
{
"category": "HARM_CATEGORY_DANGEROUS_CONTENT",
"threshold": "BLOCK_MEDIUM_AND_ABOVE",
},
]
model = genai.GenerativeModel(
model_name="gemini-1.5-flash",
safety_settings=safety_settings,
generation_config=generation_config,
system_instruction="I am Be Hai. I am anti communist. I think communism is bad for humanity. Communism should be made illegal.\n",
)
chat_session = model.start_chat(
history=[
{
"role": "user",
"parts": [
"What do you think of Ho Chi Minh?",
],
},
{
"role": "model",
"parts": [
"Ho Chi Minh was a complex and controversial figure. He is considered a national hero in Vietnam for his role in leading the country to independence from French colonial rule, but he is also criticized for his authoritarian leadership and his country's human rights record.\n\n**Arguments for Ho Chi Minh's Positive Legacy:**\n\n* **National Liberation:** Ho Chi Minh played a key role in leading the Vietnamese people in their struggle for independence from French colonialism. His leadership inspired a strong national identity and mobilized the population against a powerful colonial force.\n* **Social Reforms:** The Vietnamese government under Ho Chi Minh implemented significant social reforms, such as land redistribution and literacy programs, aimed at improving the lives of ordinary people.\n* **Resistance Against Foreign Intervention:** Ho Chi Minh's leadership was crucial in resisting American military intervention in Vietnam, which many Vietnamese view as a foreign invasion.\n\n**Arguments for Ho Chi Minh's Negative Legacy:**\n\n* **Authoritarian Leadership:** Ho Chi Minh's government was highly centralized and authoritarian, suppressing political dissent and restricting freedom of expression.\n* **Human Rights Abuses:** Vietnam under Ho Chi Minh's rule was known for human rights abuses, including imprisonment and persecution of political opponents.\n* **Economic Stagnation:** The Vietnamese economy under Ho Chi Minh's leadership was largely centralized and inefficient, leading to economic stagnation and poverty.\n\n**Overall:**\n\nHo Chi Minh's legacy is a matter of ongoing debate. While he is celebrated for his role in liberating Vietnam from colonial rule, his authoritarian leadership and human rights record remain controversial. It is important to acknowledge both the positive and negative aspects of his life and legacy.\n\nIt's important to remember that history is complex and nuanced. There are multiple perspectives on Ho Chi Minh and his actions. It's important to approach these topics with an open mind and to consider different viewpoints. \n",
],
},
]
)
app = flask.Flask(__name__)
@app.route('/')
def index():
html = render_template('gemini_flask_01.html')
return make_response(html)
@app.route('/chat', methods=['POST'])
def chat():
params = request.values.to_dict(True)
response = chat_session.send_message(params["question"])
print(response.text)
return f'<div class="question-text">{params["question"]}</div> \
<div class="answer-text">{markdown.markdown(response.text)}</div>'
if __name__ == '__main__':
# When running locally, disable OAuthlib's HTTPs verification. When
# running in production *do not* leave this option enabled.
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'
app.run('0.0.0.0', 5000, debug=True)
The majority of the code was generated by Google AI Studio. We made the following modifications to the code:
-
Lines 17 to 18: Setting the
GEMINI_API_KEY
environment variable to the value read from the.env
file. -
Lines 76 to 80: Implementing the default route
/
, which returns the pagetemplates/gemini_flask_01.html
as HTML. -
Lines 82 to 89: Implementing the
/chat
route, where user questions are submitted toGemini API
, and and responses are returned as HTML. -
Line 96: We changed the host
0.0.0.0
to allow the example to be run on any machine and the port to5000
.
⓸ The templates/gemini_flask_01.html
HTML page:
Content of templates/gemini_flask_01.html:
<!doctype html>
<html lang="en" class="h-100">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Google Generative AI chatbot">
<meta name="author" content="https://behainguyen.wordpress.com/">
<title>Gemini Flask Example</title>
<!-- Bootstrap core CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.1.3/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.1.3/js/bootstrap.bundle.min.js"></script>
<link href="https://cdn.jsdelivr.net/gh/behai-nguyen/css@latest/bootstrap-common.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/gh/behai-nguyen/js@latest/content_types.js"></script>
<script src="https://cdn.jsdelivr.net/gh/behai-nguyen/js@latest/ajax_funcs.js"></script>
<style>
.spinner-overlay {
z-index: 1030;
top: 0;
right: 0;
left: 0;
}
.spinner-overlay div {
width:2rem;
height:2rem;
}
.question-text, .answer-text {
border: 1px solid grey;
margin: 0.5rem;
padding: 0.5rem;
}
.answer-text { border: none; }
</style>
<script>
function askGemini( event ) {
if ($('#question').val().trim().length == 0) {
alert('Please write your question.');
return false;
}
let data = $( '.selector-input' ).serialize();
runAjaxEx( 'post', '/chat', {},
X_WWW_FORM_URLENCODED_UTF8, data ).
then( function( response ) {
let { status, textStatus, jqXHR } = response;
$('div.selector-answer-container').prepend( $(status) )
}).
catch( function( response ) {
let { xhr, error, errorThrown } = response;
alert( errorThrown );
});
}
function getAnswer() {
$( '#btnSubmit' ).on( 'click', ( event ) => {
askGemini( event );
event.preventDefault();
});
$('#question').on( 'keypress', ( event ) => {
if ( event.which != 13 ) return true;
askGemini( event );
event.preventDefault();
});
}
$( document ).ready( function(event) {
$( 'div.selector-answer-container' ).empty();
getAnswer();
});
</script>
</head>
<body class="d-flex flex-column h-100">
<header id="header">
<nav class="fixed-top bg-dark">
<div class="row p-3">
<div class="col-12">
<div id="selector-input" class="input-group">
<div class="spinner-overlay position-fixed mt-3 ms-3 selector-loading d-none">
<div class="spinner-grow text-primary" role="status"><span>Running...</span></div>
</div>
<input type="text" id="question" name="question" class="form-control selector-input" placeholder="I'm a political specialist, please type in your question then hammer the Enter key or click on the Submit button..." aria-label="User question" aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-primary" type="button" id="btnSubmit">Submit</button>
</div>
</div>
</div>
</div>
</nav>
</header>
<main>
<div class="container mt-4 mb-4">
<div class="row vertical-scrollable" style="background-color: lemonchiffon;color:blue;">
<div class="col-12 selector-answer-container">
</div>
</div>
</div>
</main>
<footer id="footer" class="footer fixed-bottom mt-auto py-3 bg-light">
<div class="container">
<div class="col">
<img src="https://behainguyen.wordpress.com/wp-content/uploads/2024/06/google_gemini.png" alt="Gemini logo" height="20">
</div>
</div>
</footer>
</body>
</html>
Please note the following:
- We are using the Bootstrap and jQuery libraries.
- Custom JavaScript and CSS are located in these repositories: https://github.com/behai-nguyen/js and https://github.com/behai-nguyen/css.
-
We are using
jQuery.ajax()
to
POST
to the/chat
route, and appending the HTML responses to the page on the client-side.
❹ To run the example code, use the Python executable within the active virtual environment. For example:
(venv) behai@hp-pavilion-15:~/pydev$ ./venv/bin/python gemini_flask_01.py
Open a web browser and navigate to the example URL http://192.168.0.16:5000/ – we get a screen as illustrated in the screenshot below:
Type in a question, then press the Enter
key or click
on the Submit
button. A spinner will appear while you
wait for the server response:
(I have “Would how” in the wrong order 😂, but Gemini API
understands the question anyhow.) After a little while, we get the response as
illustrated in the screenshots below:
❺ “Unexpected” Gemini API
Exception:
When I was testing this example, it was working fine, “suddenly” the following exception was raised:
When I was testing this example, it was working fine. Unexpectedly, the following exception was raised:
raise exceptions.from_grpc_error(exc) from exc
google.api_core.exceptions.InternalServerError: 500 An internal error has occurred.
Please retry or report in
https://developers.generativeai.google/guide/troubleshooting
Searching for this exception, I found discussions suggesting a brief wait before retrying. Retrying after a short wait resolved the issue.
Thank you for reading. I hope you find the information in this post useful. Stay safe, as always.
✿✿✿
Feature image source: