Local-first Python project for a mobile-app personalization system that uses one Ollama-hosted LLM as the core decision engine for recommendations and notification timing.
- Generates realistic synthetic commerce and app-usage data locally.
- Summarizes raw user activity into compact structured features.
- Retrieves a small candidate set of products before the LLM call.
- Uses one local LLM through Ollama to return strict JSON with:
- ranked products
- recommendation reasons
- send or do-not-send notification decision
- best send hour
- short notification title and body
- Exposes the flow through FastAPI.
- Includes offline evaluation and pytest coverage.
ai_personalization/
├── data/
│ ├── raw/
│ ├── synthetic/
│ └── processed/
├── models/
├── outputs/
├── src/
├── tests/
├── requirements.txt
├── README.md
└── run_demo.py
PowerShell:
cd ai_personalization
python -m venv .venv
.\.venv\Scripts\Activate.ps1python -m pip install --upgrade pip
pip install -r requirements.txtInstall Ollama from https://ollama.com/download.
After installation, confirm it is available:
ollama --versionThe default model name in this project is llama3.1.
ollama pull llama3.1You can switch models with environment variables:
$env:OLLAMA_MODEL="qwen2.5:7b-instruct"
$env:OLLAMA_HOST="http://localhost:11434"Option 1, through the API after it starts:
curl -Method POST http://127.0.0.1:8000/generate-synthetic-data -Headers @{"Content-Type"="application/json"} -Body '{"user_count":5000,"product_count":600,"session_count":60000}'Option 2, from Python:
python -c "from src.config import get_settings; from src.synthetic_data import generate_synthetic_dataset; print(generate_synthetic_dataset(get_settings()))"The generator writes CSV files into data/synthetic/ and mirrors them into data/processed/personalization.db.
uvicorn src.api:app --host 127.0.0.1 --port 8000 --reloadAvailable endpoints:
GET /healthPOST /generate-synthetic-dataPOST /build-user-summary/{user_id}POST /recommend/{user_id}POST /notify/{user_id}POST /full-decision/{user_id}GET /products/{product_id}GET /users/{user_id}/summary
python run_demo.pyThe demo will generate synthetic data if it does not exist, select a representative user, and print the full decision JSON.
python -m src.evaluationOutputs are written to outputs/:
evaluation_detail.csvevaluation_metrics.jsonevaluation_metrics.png
pytest -q- Product retrieval is handled by lightweight local filtering, not a second ML model.
- The LLM is the single reasoning and ranking engine for recommendations and notifications.
- If Ollama is unavailable or returns invalid JSON, the code falls back to deterministic heuristics so tests and local development can still run.