Introduction
In this first part of our tutorial series, we'll focus on building a robust Flask backend that integrates with Google's Gemini AI to generate personalized sustainability tips. We'll cover setting up the development environment, implementing the API endpoints, and handling AI interactions.
Project Overview
SustainAI Tips is a modern web application that helps users adopt sustainable living practices through personalized recommendations. The backend serves as the bridge between our frontend interface and the Gemini AI model, handling:
- User input processing and validation
- AI model interactions and prompt engineering
- Response formatting and error handling
- Cross-Origin Resource Sharing (CORS) configuration
Prerequisites
Before we begin, ensure you have:
- Python 3.8 or higher installed
- A Google Gemini AI API key
- Basic knowledge of Python and REST APIs
- A code editor (VS Code recommended)
Project Structure
backend/
├── app.py # Main application file
├── requirements.txt # Project dependencies
├── .env # Environment variables
└── README.md # Backend documentation
Step 1: Setting Up the Development Environment
- First, create the project directory and set up a virtual environment:
mkdir -p sustainai-web-tips/backend
cd sustainai-web-tips/backend
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
- Create and populate
requirements.txt
:
# Flask - Web framework for building the API
flask==2.0.1
# Flask-CORS - Handle Cross-Origin Resource Sharing
flask-cors==3.0.10
# Google Generative AI - Interface with Gemini AI
google-generativeai==0.3.0
# Python-dotenv - Load environment variables
python-dotenv==0.19.0
- Install the dependencies:
pip install -r requirements.txt
- Create
.env
file:
# Google Gemini AI API key
# Get your key from: https://makersuite.google.com/app/apikey
GOOGLE_API_KEY=your_gemini_api_key_here
Step 2: Implementing the Backend Server
Create app.py
with the following code:
"""
SustainAI Tips Backend Server
This Flask application serves as the backend for the SustainAI Tips web application.
It uses the Google Gemini 1.5 Pro AI model to generate personalized sustainability tips
based on user location and habits.
Key Components:
- Flask server with CORS support
- Google Gemini AI integration
- Structured prompt engineering
- Error handling and validation
Author: Antony Ngemu
Date: March 2025
"""
import os
from flask import Flask, request, jsonify
from flask_cors import CORS
import google.generativeai as genai
from dotenv import load_dotenv
from typing import List, Dict, Union, Optional
# Load environment variables from .env file
load_dotenv()
# Initialize Flask application
app = Flask(__name__)
# Configure CORS for frontend integration
# This allows our Next.js frontend to make requests to this backend
CORS(app, resources={
r"/api/*": {
"origins": ["http://localhost:3000", "http://127.0.0.1:3000"],
"methods": ["POST", "OPTIONS"],
"allow_headers": ["Content-Type"]
}
})
def initialize_ai_model() -> None:
"""
Initialize the Google Gemini AI model with API key.
Raises:
ValueError: If GOOGLE_API_KEY is not found in environment variables
Exception: If model initialization fails
"""
try:
api_key = os.getenv('GOOGLE_API_KEY')
if not api_key:
raise ValueError("GOOGLE_API_KEY not found in environment variables")
genai.configure(api_key=api_key)
except Exception as e:
print(f"Error initializing AI model: {str(e)}")
raise
def construct_ai_prompt(location: str, habits: str) -> str:
"""
Construct a detailed prompt for the AI model.
Args:
location (str): User's location for location-specific tips
habits (str): User's current habits for targeted recommendations
Returns:
str: Formatted prompt string for the AI model
"""
return f"""
Generate practical and personalized sustainability tips for someone in {location}
with the following habits: {habits}.
Format the response in markdown with the following categories:
1. Quick Wins (Easy to implement immediately)
2. Sustainable Living
3. Transportation & Mobility
4. Community & Social Impact
5. Environmental Protection
For each tip:
- Make it specific to {location}
- Include cost implications or savings
- Make it actionable and practical
- Consider local resources and infrastructure
- Use bullet points with bold headers
Start each category with a markdown header (##) and number.
Format each tip as a markdown bullet point (*).
Use bold (**) for tip headers.
"""
def generate_ai_tips(location: str, habits: str) -> List[str]:
"""
Generate personalized sustainability tips using Google Gemini AI.
Args:
location (str): User's location for location-specific tips
habits (str): User's current habits for targeted recommendations
Returns:
List[str]: List of markdown-formatted tips organized by categories
Raises:
Exception: If there's an error generating tips from the AI model
"""
try:
# Initialize Gemini 1.5 Pro model
model = genai.GenerativeModel('gemini-1.5-pro')
# Generate AI response using the constructed prompt
prompt = construct_ai_prompt(location, habits)
response = model.generate_content(prompt)
if not response or not response.text:
raise ValueError("Empty response from AI model")
# Process and clean the response
tips = response.text.strip().split('\n')
return [tip.strip() for tip in tips if tip.strip()]
except Exception as e:
print(f"Error generating tips: {str(e)}")
raise
def validate_input(data: Dict[str, str]) -> Optional[str]:
"""
Validate the input data from the request.
Args:
data (Dict[str, str]): Request data containing location and habits
Returns:
Optional[str]: Error message if validation fails, None if successful
"""
if not data:
return "Request body is empty"
location = data.get('location', '').strip()
habits = data.get('habits', '').strip()
if not location:
return "Location is required"
if not habits:
return "Habits are required"
return None
@app.route('/api/tips', methods=['POST'])
def get_tips() -> Union[Dict, tuple]:
"""
API endpoint to generate sustainability tips.
Expects POST request with JSON body containing:
- location: string
- habits: string
Returns:
Union[Dict, tuple]: JSON response with generated tips or error message
"""
try:
# Extract and validate input data
data = request.get_json()
validation_error = validate_input(data)
if validation_error:
return jsonify({
'error': validation_error
}), 400
# Generate tips using AI
tips = generate_ai_tips(
location=data['location'].strip(),
habits=data['habits'].strip()
)
return jsonify({'tips': tips})
except Exception as e:
# Log error and return safe error message
print(f"Error processing request: {str(e)}")
return jsonify({
'error': 'Failed to generate tips. Please try again.'
}), 500
if __name__ == '__main__':
try:
# Initialize AI model before starting the server
initialize_ai_model()
# Run Flask development server
app.run(debug=True)
except Exception as e:
print(f"Failed to start server: {str(e)}")
Step 3: Understanding the Implementation
Let's break down the key components of our backend:
-
Environment Setup
- We use
python-dotenv
to manage environment variables - CORS is configured to allow requests from our Next.js frontend
- Type hints are used throughout for better code maintainability
- We use
-
AI Model Integration
- The
initialize_ai_model()
function sets up Gemini AI - Error handling ensures graceful failure if API key is missing
- Model initialization happens before server start
- The
-
Prompt Engineering
- The
construct_ai_prompt()
function creates structured prompts - Categories are clearly defined for consistent output
- Markdown formatting is specified for frontend rendering
- The
-
Input Validation
- The
validate_input()
function checks request data - Empty or missing fields are caught early
- Validation errors return clear messages
- The
-
Error Handling
- Try-except blocks catch and log errors
- User-facing error messages are sanitized
- Detailed logs help with debugging
Step 4: Testing the Backend
- Start the server:
python app.py
- Test the API endpoint using curl:
curl -X POST http://localhost:5000/api/tips \
-H "Content-Type: application/json" \
-d '{"location":"San Francisco","habits":"driving car, using plastic bags"}'
Next Steps
In Part 2 of this tutorial, we'll:
- Build the Next.js frontend
- Create a responsive UI with React Bootstrap
- Implement the tips display with animations
- Add error handling and loading states
The complete source code is available on GitHub [].
Top comments (1)
very good👍