Skip to content

Repository files navigation

Review Intelligence Pipeline

A small event-driven pipeline: customer reviews are submitted via REST, published to Kafka, enriched asynchronously with AI (sentiment, category, summary), and stored in Postgres.

Stack: Spring Boot · Apache Kafka · Spring AI (Gemini) · PostgreSQL · Docker

How it works

POST /reviews → saved to Postgres (PENDING) → published to Kafka
                                                      ↓
                                          Consumer picks up message
                                                      ↓
                                    Spring AI calls Gemini → {sentiment, category, summary}
                                                      ↓
                                          Saved back to Postgres (ENRICHED)

The API responds immediately (202 Accepted) while the AI enrichment happens in the background, that's the reason Kafka is in the design at all.

Setup

Prerequisites: Java 17+, Maven, Docker Desktop, a free Gemini API key

  1. Configure secrets: copy the example files and fill in your own values:

    cp .env.example .env
    cp src/main/resources/application-secrets.properties.example src/main/resources/application-secrets.properties

    Fill in your Postgres credentials and Gemini API key in both files.

  2. Start infrastructure:

    docker compose up -d
  3. Run the app:

    mvn clean install
    mvn spring-boot:run

API Endpoints

| Method | Endpoint | Description | | POST | /reviews | Submit a review for enrichment | | GET | /reviews | List all reviews | | GET | /reviews/{id} | Get a single review | | GET | /reviews/stats | Sentiment counts across all enriched reviews |

Example

Request:

json

POST /reviews {"text": "I loved the burger at McDonald's. I was happy kid."}```

Immediate response: (202 Accepted):

json

{ "id": "add13edb-f92d-4713-9b2e-e15bf58c0072", "rawText": "I loved the burger at McDonald's. I was happy kid.", "sentiment": null, "category": null, "summary": null, "status": "PENDING", "createdAt": "2026-07-14T21:10:55.926691Z" }

After a couple seconds: (GET /reviews/{id}):

json

{ "id": "add13edb-f92d-4713-9b2e-e15bf58c0072", "rawText": "I loved the burger at McDonald's. I was happy kid.", "sentiment": "POSITIVE", "category": "product quality", "summary": "The reviewer loved the burger at McDonald's and was very happy with it.", "status": "ENRICHED", "createdAt": "2026-07-14T21:10:55.926691Z" }

Aggregate stats: (GET /reviews/stats):

json

{ "POSITIVE": 1, "NEGATIVE": 1, "NEUTRAL": 1 }

Screenshots

S-1: POST Request and Response POST request

S-2: GET Request and check the status with the ID. GET request

S-3: GET Request and list all the status and their count. GET1 request

Notes

  • Uses Gemini's free tier — expect rate limits if testing with many requests quickly.
  • ddl-auto: update auto-creates the schema; not intended for production use.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages