Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
.git
.github
.venv
__pycache__
*.pyc
.env
.env.example
runs/
screenshots/
integrations/
PYTHIA.app/
PYTHIA.command
run-all.sh
*.md
LICENSE
logo.png
demo.mp4
.gitignore
.dockerignore
docker-compose.yml
33 changes: 33 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
FROM python:3.13-alpine AS builder
WORKDIR /app

# Install uv without pulling pip's cache into the image
RUN pip install --no-cache-dir uv

# Resolve & install dependencies first — this layer is cached unless
# pyproject.toml or uv.lock change, so engine-only edits don't reinstall deps.
COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-dev

COPY engine/ ./engine/

# ── runtime stage ──
FROM python:3.13-alpine AS runtime
WORKDIR /app

# The virtualenv has everything; just copy it plus the engine source.
COPY --from=builder /app/.venv /app/.venv
COPY --from=builder /app/engine /app/engine
COPY --from=builder /app/pyproject.toml /app/

ENV PATH="/app/.venv/bin:$PATH" \
PYTHIA_ROOT="/app" \
PYTHONUNBUFFERED=1

EXPOSE 8088

# Lightweight root-route healthcheck — matches the GET / route added in server.py
HEALTHCHECK --interval=30s --timeout=5s --start-period=40s --retries=3 \
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8088/').read()" || exit 1

CMD ["python", "-m", "engine.run"]
53 changes: 53 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: pythia

services:
osiris:
image: ghcr.io/aiacos/osiris:latest
container_name: osiris
ports:
- "3000:3000"
environment:
- NODE_OPTIONS=--dns-result-order=ipv4first
- NODE_ENV=production
- PORT=3000
- HOSTNAME=0.0.0.0
extra_hosts:
- "host.docker.internal:host-gateway"
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:3000/api/health"]
interval: 15s
timeout: 5s
start_period: 30s
retries: 5
restart: unless-stopped

pythia:
build:
context: .
dockerfile: Dockerfile
container_name: pythia-engine
ports:
- "8088:8088"
environment:
- OSIRIS_URL=http://osiris:3000
- ENGINE_HOST=0.0.0.0
- ENGINE_PORT=8088
# LLM defaults point at a host-side Ollama; override via .env or shell env.
# host.docker.internal works on Docker Desktop; on Linux add --add-host or use
# the host network's IP (e.g. 172.17.0.1 for default bridge).
- LLM_BASE_URL=${LLM_BASE_URL:-http://host.docker.internal:11434/v1}
- LLM_API_KEY=${LLM_API_KEY:-ollama}
- LLM_MODEL=${LLM_MODEL:-llama3.1}
- ORACLE_TEMPERATURE=${ORACLE_TEMPERATURE:-0.5}
- ORACLE_TIMEOUT_SEC=${ORACLE_TIMEOUT_SEC:-180}
- HORIZONS=${HORIZONS:-24h,week,month,year}
- PREDICTIONS_PER_HORIZON=${PREDICTIONS_PER_HORIZON:-3}
- LOOP_INTERVAL_SEC=${LOOP_INTERVAL_SEC:-900}
- SENSE_INTERVAL_SEC=${SENSE_INTERVAL_SEC:-180}
- SWARM_ENABLED=${SWARM_ENABLED:-true}
depends_on:
osiris:
condition: service_healthy
extra_hosts:
- "host.docker.internal:host-gateway"
restart: unless-stopped
6 changes: 6 additions & 0 deletions engine/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ async def health():
return {"status": "ok", "service": "pythia-oracle", "config": CONFIG.summary()}


@app.get("/")
async def root():
"""Root health-check route for load balancers and service monitors."""
return {"status": "ok", "service": "pythia-oracle", "version": app.version}


@app.get("/config")
async def config():
return CONFIG.summary()
Expand Down