RevuAI is a Google Play Store review intelligence platform. It combines a Chrome extension with a FastAPI backend to collect app reviews, classify sentiment, identify recurring topics, and generate product insights with an LLM.
Table of Contents
- Analyze newest, most relevant, or all available reviews for a Play Store app.
- Classify reviews as positive, neutral, or negative with a registered Linear SVM model.
- Report sentiment percentages and the most helpful reviews in each sentiment group.
- Cluster review topics with MiniLM embeddings, UMAP, HDBSCAN, and KeyBERT.
- Generate a readable summary and recommendations with Groq.
- Cache recent analyses to make repeated extension requests faster.
- Maintain an append only review data lake in PostgreSQL/Supabase for model retraining.
- Track experiments and register Champion models through MLflow and DagsHub.
flowchart LR
Extension[Chrome extension] --> API[FastAPI API]
API --> Scraper[Google Play scraper]
API --> Sentiment[Champion sentiment model]
API --> Topics[Topic clustering]
API --> LLM[Groq LLM insight]
subgraph DataOps[Data and model lifecycle]
ETL[Scheduled production ETL] --> Data[(PostgreSQL / Supabase)]
Data --> Training[Scheduled monthly retraining]
Training --> Evaluation[Evaluate against Champion]
Evaluation --> Registry[MLflow / DagsHub registry]
Registry --> Sentiment
end
subgraph Delivery[CI/CD delivery]
Push[Push to main] --> Tests[Pytest]
Tests --> Build[Build Docker image]
Build --> GHCR[Push to GitHub Container Registry]
GHCR --> Deploy[Deploy to EC2]
Deploy --> Health[Health check]
end
ETL -. monthly schedule .-> Training
Evaluation -- Champion promoted --> Build
The inference request runs through these stages:
- Scrape reviews from Google Play.
- Predict sentiment with the registered Champion model and TF-IDF vectorizer.
- Calculate the sentiment distribution and select top reviews by helpfulness.
- Cluster reviews by sentiment and extract representative topics.
- Send the summarized results to Groq for a product-oriented insight.
- Python 3.11
- A PostgreSQL-compatible database for ETL and training data
- A Groq API key for LLM insight generation
- Access to the MLflow/DagsHub model registry for production inference
- Docker, if running the containerized service
- Google Chrome, if using the extension
Create and activate a virtual environment:
python -m venv .venv
Set-ExecutionPolicy -Scope Process -ExecutionPolicy RemoteSigned
.\.venv\Scripts\Activate.ps1Install the full development dependency set:
python -m pip install --upgrade pip
python -m pip install -r requirements.txtFor the production API only, use requirements-runtime.txt instead. The Docker image installs the CPU-only PyTorch build and the runtime dependencies automatically.
Copy .env.example to .env and replace the placeholders:
Copy-Item .env.example .envRequired values:
DATABASE_URL=postgresql+asyncpg://USER:PASSWORD@HOST:5432/DATABASE
GROQ_API_KEY=your_groq_api_key
DAGSHUB_USERNAME=your_dagshub_username
DAGSHUB_USER_TOKEN=your_dagshub_tokenDAGSHUB_USERNAME and DAGSHUB_TOKEN are also supported by the scheduled ML workflow. Keep .env out of version control and never commit API keys or database credentials.
Optional runtime settings:
| Variable | Default | Purpose |
|---|---|---|
PORT |
8000 |
Port used by python main.py |
TORCH_NUM_THREADS |
4 |
CPU threads used by PyTorch |
RESULT_CACHE_TTL_SECONDS |
1800 |
In-memory inference cache lifetime |
GROQ_MODEL |
openai/gpt-oss-20b |
Groq model used for insight generation |
The ML pipeline reads model and training settings from config/settings.yml. The database schema and connection setup are defined in database/models.py and database/connection.py.
Start the service with Uvicorn:
python -m uvicorn main:app --host 0.0.0.0 --port 8000Or run the application module directly:
python main.pyThe API loads the Champion sentiment model and the all-MiniLM-L6-v2 sentence embedding model during startup. The first startup may download model artifacts and requires access to the configured MLflow/DagsHub registry.
Open the interactive API documentation at:
http://localhost:8000/docshttp://localhost:8000/redoc
Returns a service description.
Reports whether the prediction and embedding models are loaded, along with the number of cached results.
Request body:
{
"app_id": "com.supercell.clashofclans",
"scraping_method": "new_reviews",
"force_refresh": false
}scraping_method accepts new_reviews, relevant_reviews, or all_reviews. force_refresh bypasses the process-local cache.
Example PowerShell request:
Invoke-RestMethod -Method Post `
-Uri http://localhost:8000/inference/analyze `
-ContentType "application/json" `
-Body '{"app_id":"com.supercell.clashofclans","scraping_method":"new_reviews"}'The response includes review_count, sentiment_percentages, top_reviews, topic_summary, llm_insight, insight_generated_at, execution_time_seconds, and cache_hit.
Removes the cached result for an app. The optional scraping_method query parameter defaults to new_reviews.
Invoke-RestMethod -Method Delete `
-Uri "http://localhost:8000/inference/cache/com.supercell.clashofclans?scraping_method=new_reviews"- Start the API locally or configure an accessible backend.
- Open
chrome://extensionsin Chrome. - Enable Developer mode.
- Select Load unpacked and choose the
extensiondirectory. - Open a Google Play app page, or paste its package ID into the extension.
- Choose a review source and select Analyze Reviews.
The extension can detect the package ID from the active Play Store tab. Its current backend options are defined in extension/popup.js, including the local service at http://localhost:8000 and the configured cloud service. Update the cloud URL and extension/manifest.json host permissions when deploying to a different backend.
The standard ETL pipeline reads datasource/raw/app_reviews_labeled.csv, transforms the review text and labels, and appends deduplicated records to the reviews_datalake table:
python -m src.pipelines.etl_pipelineThe production pipeline scrapes reviews from selected apps, labels them with the configured transformer model, transforms them, and loads them into the database:
python -m src.pipelines.etl_pro_pipelineThe ML pipeline fetches recent data, creates TF-IDF features, trains and evaluates a balanced LinearSVC, tracks the run with MLflow, and registers the model. A new model is promoted to the Champion alias only when it meets the configured promotion rules:
python -m src.pipelines.ml_pipelineTraining settings, including the test split and MLflow model name, are in config/settings.yml.
For command-line experimentation, the inference pipeline can be run without the API:
python -m src.pipelines.inference_pipelineThis requires the same model registry, embedding model, and Groq configuration as the API.
Build and run the production image:
docker build -f dockerfile -t revuai:latest .
docker run --rm -p 8000:8000 --env-file .env revuai:latestThe container exposes port 8000, runs one Uvicorn worker, and includes a health check against /health.
Run the test suite:
python -m pytestUseful development commands:
make install-dev
make test
make test-coverage
make lint
make format
make cleanThe test suite uses lightweight fakes for model loading, scraping, and LLM calls so API tests do not require network access or production credentials.
RevuAI uses GitHub Actions for continuous integration, scheduled data refreshes, model retraining, and deployment. The workflows are defined in .github/workflows/.
On every push to main, the deployment workflow:
- Checks out the repository and installs the Python 3.11 dependencies.
- Runs the complete
pytestsuite. - Builds a production Docker image for
linux/amd64. - Publishes both a commit-specific image and
latestto GitHub Container Registry. - Connects to the configured EC2 host over SSH.
- Pulls the new image, replaces the running container, and checks the
/healthendpoint.
The deployment workflow can also be started manually or called by the monthly training workflow. Deployment concurrency is serialized so two deployments cannot replace one another at the same time.
The production learning cycle runs on the first day of every month:
- At
00:00 UTC,monthly_etl.ymlruns the production ETL pipeline. It scrapes reviews, labels them, transforms the records, and appends deduplicated data to the PostgreSQL/Supabasereviews_datalaketable. - At
03:00 UTC,monthly_ml_training.ymlreads the latest data from the data lake and trains a new TF-IDF plus balancedLinearSVCsentiment model. - The training run is tracked in MLflow and the model is registered in DagsHub.
- The new model is evaluated against the current Champion using the configured test F1 score.
- The Champion alias is updated only when the new model satisfies the promotion rules in config/settings.yml.
- The workflow reads the pipeline's
CHAMPION_UPDATED=true|falsesignal. If the Champion changed, it calls the deployment workflow; otherwise, the existing production service remains unchanged.
Both scheduled workflows also support manual execution with GitHub Actions' Run workflow control. Concurrency groups prevent overlapping ETL or training runs.
| Workflow | Trigger | Responsibility |
|---|---|---|
ci.yml |
Push to main |
Install dependencies and run tests |
deploy.yml |
Push to main, manual, or reusable call |
Test, build, publish, and deploy the API |
monthly_etl.yml |
Monthly at 00:00 UTC or manual | Scrape, label, transform, and load reviews |
monthly_ml_training.yml |
Monthly at 03:00 UTC or manual | Train, evaluate, register, and conditionally deploy a model |
Configure the repository secrets required by the workflows before enabling scheduled runs:
DATABASE_URLfor the production ETL workflow.DAGSHUB_USERNAMEandDAGSHUB_TOKENfor MLflow tracking and model registration.EC2_HOST,EC2_USERNAME, andEC2_SSH_KEYfor container deployment.
main.py FastAPI application and startup lifecycle
router/ API routes and request validation
src/inference/ Scraping, prediction, clustering, and LLM insight logic
src/etl/ Extract, transform, and load components
src/ml/ Training, MLflow tracking, and model registry logic
src/pipelines/ Runnable ETL, ML, and inference workflows
database/ SQLAlchemy connection and review models
config/ YAML training settings and LLM prompt constants
datasource/ Source datasets and labeling utilities
extension/ Chrome extension popup and manifest
tests/ API, ETL, inference, and ML tests
- The inference cache is process-local and is cleared when the service restarts. It is not shared between multiple workers.
- Full inference can take several minutes because scraping, clustering, and LLM generation are performed in sequence.
- A missing
GROQ_API_KEYprevents insight generation and causes full inference requests to fail. - Google Play scraping depends on the availability and behavior of the upstream Play Store service.
- The extension's cloud endpoint is configured in source code. Use HTTPS and update host permissions before exposing a production deployment.
- Keep dependency versions and model registry credentials controlled in deployment environments for reproducible builds.
See LICENSE.