AI Engine API¶
The serving REST API: search, geo, recommendation, narrative, and the recsys ingest webhook.
It wraps the ai-engine library and reads Qdrant and Redis.
Prerequisites¶
- Qdrant and Redis running (or reachable URLs).
- A populated collection (run the Content Engine once).
- An LLM endpoint for narratives (Ollama or OpenRouter), optional.
Configure¶
Set at least:
QDRANT_API_URL=http://qdrant:6333 # or http://localhost:6333
REDIS_URL=redis://redis:6379/0
COLLECTION_NAME=omeka-items
EMBEDDING_MODEL=sentence-transformers/all-MiniLM-L6-v2
# narratives (optional):
OPENROUTER_API_KEY=... # or OLLAMA_BASE_URL=...
Full list: Configuration. Keycloak and the LLM endpoint are run by other teams; you only set their URLs/keys here.
Run with Docker¶
The project ships a Dockerfile (python:3.12-slim, Poetry, uvicorn service:app on 8000).
cd ai-engine-api
docker build -t ai-engine-api:local .
docker run -d --name ai-engine-api --env-file .env -p 8000:8000 ai-engine-api:local
Or run it inside the full local stack in Local (Docker Compose).
Run without Docker¶
cd ai-engine-api
poetry install --only main
poetry run uvicorn service:app --host 0.0.0.0 --port 8000
Verify¶
curl http://localhost:8000/ # {"status":"ok", ...}
curl "http://localhost:8000/api/search?q=Bergen-Belsen"
curl "http://localhost:8000/api/recommend?user_id=u1&limit=5"
On boot the logs say Recsys router mounted at /api when the engine wired up. If you see
Recsys router NOT mounted, check REDIS_URL / QDRANT_API_URL.
The interactive reference is the AI Engine API page.
Production¶
- Build and push the image to your registry; run it as a Deployment behind TLS.
- Point
QDRANT_API_URL/REDIS_URLat managed services. - The serve path is stateless (reads the user model from Redis), so scale horizontally.
- Tighten CORS from the default allow-all to your front-end origin.
Kubernetes¶
Run it as a Deployment with several replicas behind a Service and an Ingress (TLS). Inject
config from a Secret/ConfigMap rather than a baked .env.
apiVersion: apps/v1
kind: Deployment
metadata: { name: ai-engine-api }
spec:
replicas: 3
selector: { matchLabels: { app: ai-engine-api } }
template:
metadata: { labels: { app: ai-engine-api } }
spec:
containers:
- name: api
image: registry.example.com/memorise/ai-engine-api:1.0
ports: [{ containerPort: 8000 }]
envFrom:
- secretRef: { name: ai-engine-secrets } # QDRANT_API_KEY, OPENROUTER_API_KEY, KEYCLOAK_*
- configMapRef: { name: ai-engine-config } # QDRANT_API_URL, REDIS_URL, COLLECTION_NAME, EMBEDDING_MODEL
readinessProbe: { httpGet: { path: /, port: 8000 } }
livenessProbe: { httpGet: { path: /, port: 8000 } }
---
apiVersion: v1
kind: Service
metadata: { name: ai-engine-api }
spec:
selector: { app: ai-engine-api }
ports: [{ port: 8000 }]
In-cluster, point it at the other services: QDRANT_API_URL=http://qdrant:6333,
REDIS_URL=redis://redis:6379/0. Full manifests + hardening: Cloud and production.