DEV Community

Cover image for From Code to Cloud: Mastering the Gemini API with a Seamless CI/CD Pipeline
Kshitij Chaudhary
Kshitij Chaudhary

Posted on • Edited on

From Code to Cloud: Mastering the Gemini API with a Seamless CI/CD Pipeline

Introduction

In today's dynamic world of software development, APIs(Application Programming Interfaces) serve as the backbone of software development, which acts as bridges between different applications for communicating and sharing data seamlessly. It allows developers to leverage the existing features, functions, and services to accelerate development process with enhancement of application capabilities. Among the tons of APIs available, the Gemini API stands out offering AI capabilities, which allow developers to integrate generative models into the application.

In this blog, we will explore setting up custom implementation of Gemini API, while focusing on its functionality and features. We will also discuss ensuring reliability through testing and automate the deployment process using the Continuous Integration/Continuous Deployment (CI/CD) Pipeline. By the end of this blog, we will be able to setup, test and deploy project using Gemini API, ensuring efficient workflow.


Understanding the Gemini API

Image description
Gemini API is a cutting-edge AI technology that is developed by Google and provides the developers with powerful generative capabilities. It can:

  • Generate human-like text.
  • Provide intelligent responses across various domains.
  • Process complex queries.
  • Create code snippets and analyze multimodal inputs. This API acts as strong tool for development of the applications which require dynamic, AI-powered features.

Why use CI/CD?

Continuous Integration (CI)/Continuous Deployment (CD) is software development methodology from which we can improve code quality and streamline the development process. It reduces the time between writing code and deploying it. It helps in code quality improvement by catching and fixing errors. With CI/CD, we can standardize deployment processes and minimize human error in software releases.
With the CI/CD pipeline along with the Gemini API's AI capabilities, we can create intelligent, scalable, and managed applications.


Setting Up the API

The Gemini API allows developers to leverage Google's AI models for various tasks. Here are the few steps to get started.
- Get API key from Google AI Studio
Here is the example of how to obtain the API key from Google AI Studio Interface.

Getting API Keys from Google AI Studio

- Install the Gemini API SDK
Let's use Python package manager and install the Gemini API SDK.

pip install google-generativeai

Enter fullscreen mode Exit fullscreen mode

- Set up authentication and Usage.
Let's setup authentication for Gemini API, for creating model instance and generate content.

import google.generativeai as genai
import os
from dotenv import load_dotenv

load_dotenv()  # Load API key from the .env file

def setup_gemini_api():
    """Configure the Gemini API."""
    genai.configure(api_key=os.environ["GEMINI_API_KEY"])
    model = genai.GenerativeModel(model_name="gemini-1.5-flash")
    return model

def generate_content(model, prompt):
    """Generate content using the Gemini API."""
    response = model.generate_content(prompt)
    return response.text

# Example usage
if __name__ == "__main__":
    model = setup_gemini_api()
    print(generate_content(model, "What is CI/CD?"))

Enter fullscreen mode Exit fullscreen mode

Here, we can remove the "YOUR_API_KEY" with the actual API key that we generated from Google AI Studio.

How it worked?

  • We imported the Google generative AI library which provided the necessary tools to interact with API.
  • The prompt is created, which we will send to the API for processing.
  • The initialized model processes the input and leverages Google's AI to generate the response.
  • The API returns the generated content which we can access and use in our application.

Key Points
Error Handling: We need to implement error handling to minimize potential issues during API requests.
Environment Variables: We need to store API key securely using environment variables to avoid hardcoding of sensitive information.


Integrating the Gemini API with Flask

Let's use Flask as the framework and create API endpoint and integrate essential features for handling prompts and custom instructions. We can see the key functionality implemented in the generate_content function.

from flask import Flask, request
from gemini_api import gemini_model

app = Flask(__name__)

@app.route("/chat", methods=["POST"])
def chat():
    """Endpoint to handle user prompts and generate AI responses."""
    data = request.json
    prompt = data["prompt"]
    response = gemini_model(prompt)
    return response

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)


Enter fullscreen mode Exit fullscreen mode

Features

  • This code accepts POST requests containing prompts and optional instructions.
  • The function generates a response using Gemini API.
  • It returns the output as JSON, making easy to integrate with frontend applications.

Testing the API

We need to perform testing to ensure that our integration with the Gemini API functions correctly and efficiently. In detail, testing involves proper verification of the application and its interaction with the API endpoints, handling of responses, and management of errors.
We perform two types of tests detailed below.

1. Unit Testing

Let's use Python unittest framework to validate individual components. Here is the example:

import unittest
from app import app

class TestGeminiAPI(unittest.TestCase):
    def setUp(self):
        self.client = app.test_client()

    def test_chat_endpoint(self):
        response = self.client.post("/chat", json={"prompt": "Test prompt"})
        self.assertEqual(response.status_code, 200)
        self.assertIn("Test prompt", response.data.decode())

if __name__ == "__main__":
    unittest.main()
Enter fullscreen mode Exit fullscreen mode

This unit test stimulates client request to the /generate endpoint. It assets that the response contains the expected format and content.

2. Integration Testing

For testing API endpoints, let's use requests library to stimulate HTTP requests.

import requests

def test_gemini_endpoint():
    url = "http://localhost:5000/chat"
    payload = {"prompt": "Hello, Gemini!"}
    response = requests.post(url, json=payload)
    assert response.status_code == 200
    assert "Hello, Gemini!" in response.text
Enter fullscreen mode Exit fullscreen mode

This test ensures that Gemini API integration functions correctly and handles various scenarios appropriately.


Automating Up CI/CD with Github Actions

To automate testing and deployment, Let's use Github Actions. The CI/CD pipeline automates the build, test and deployment stages/ Let's make a workflow configuration. .github/workflows/main.yml.

name: CI/CD Pipeline for Gemini API

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

jobs:
  test:
    name: Run Unit Tests
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Code
        uses: actions/checkout@v3
      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.11'
      - name: Install Dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt
      - name: Run Unit Tests
        run: |
          python -m unittest discover -s tests

  docker-build:
    name: Build and Test Docker Image
    runs-on: ubuntu-latest
    needs: test
    steps:
      - name: Checkout Code
        uses: actions/checkout@v3
      - name: Build Docker Image
        run: docker build -t gemini-api:latest -f Dockerfile .
      - name: Test Docker Container
        run: docker run --rm gemini-api:latest

  deploy:
    name: Deploy to Production
    runs-on: ubuntu-latest
    needs: docker-build
    steps:
      - name: Log in to Docker Hub
        uses: docker/login-action@v2
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}
      - name: Push Docker Image
        run: |
          docker tag gemini-api:latest ${{ secrets.DOCKER_USERNAME }}/gemini-api:latest
          docker push ${{ secrets.DOCKER_USERNAME }}/gemini-api:latest
      - name: Deploy to Server
        run: |
          ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} << 'EOF'
          docker pull ${{ secrets.DOCKER_USERNAME }}/gemini-api:latest
          docker stop gemini-api || true
          docker rm gemini-api || true
          docker run -d --name gemini-api -p 5000:5000 -e API_KEY=${{ secrets.API_KEY }} ${{ secrets.DOCKER_USERNAME }}/gemini-api:latest
          EOF

With this configuration, we can automate:

  • the pipeline ensures all dependencies and configurations are prepared. With the use of Dockerfile and DockerfileTest , we can replicate the environment anywhere.
  • the test_job stage validates the application by running predefined tests in controlled Docker environment. These tests ensure that the API works as expected.
  • Once changes are integrated to main branch, the CI/CD pipeline triggers automatically. It ensures there is no manual tasks needed for updating application.
  • In final stage, it pulls the docker image and deploys to production environment. The application is deployed at port 5000, and sensitive credentials are passed with Github Secrets.

Deployment Considerations
For smooth deployment, we consider the following.

  • We use github secrets to store sensitive environment variables like MONGODB_USERNAME, MONGODB_PASSWORD, and DOCKERHUB_PASSWORD.
  • List all the dependencies in requirements.txt file. It makes easier to replicate the development environment anywhere using the command. pip install -r requirements.txt
  • Adding the logging mechanisms help tracking application behaviour and we can debug issues promptly. For Flask app, we can use the Python's built-in logging module.
import logging  

logging.basicConfig(level=logging.INFO)  
app.logger.info("Application started successfully!")  

Enter fullscreen mode Exit fullscreen mode

Challenges and Solution

While doing every project, we come with unique challenges, and integration of Gemini API into CI/CD Pipeline was no exception. Here are some key challenges which I faced during this project along with the solutions which I implemented to overcome them.
1. Debugging Tests
I faced issues with failing the tests due to incorrect configurations and missing environment variables. This was really frustation and slowed down the development progress.
Solution: I implemented detailed logging in the test cases to capture the variable states and API responses, where i identified the failure points. I also used mock objects to stimulate API responses, which allowed me to isolate issues without depending on live calls.
2. Managing Secrets
It is challenge to manage the sensitive information like API keys, as hardcoding the values posess the security risks.
Solution: I used Github Secrets to store the sensitive information securely, allowing access in CI/CD Pipeline without exposing it on codebase. For local development, I have created a .env file which was excluded on Git.

.env file example

GEMINI_API_KEY=your_actual_api_key
MONGO_URI=your_mongo_uri

Conclusion

In this blog posts, we explored:

  • How to set up the Gemini API
  • Testing methodologies for API endpoints
  • Automating deployment using CI/CD with Github Actions.

Takeaways

  • Testing: Ensures reliabilty and scability.
  • CI/CD Pipeline: Streamline development with automated process.
  • Secure Secrets: Always protect sensitive information.

With this practice, we can create intelligent, scalable and production-ready applications.


Future Improvements

Image description
Looking ahead in coming days, I plan to expand the tests, enhance the monitoring solution using AWS CloudWatch or Prometheus for performance tracking and explore further intgerations with other APIs to enhance the functionality.
With more exploration in coming days, I aim to create the application which leverages advanced AI capabilities ensuring reliablitiy through development.


Top comments (0)