Skip to content

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

cd ai-engine-api
cp .env.example .env

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_URL at 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.