feat: Created full Docker Compose project (xpltd_chrysopedia) with Post…
- "docker-compose.yml" - ".env.example" - "docker/Dockerfile.api" - "docker/Dockerfile.web" - "docker/nginx.conf" - "backend/main.py" - "backend/requirements.txt" - "config/canonical_tags.yaml" GSD-Task: S01/T01
This commit is contained in:
parent
0904939660
commit
c404270f49
12 changed files with 332 additions and 0 deletions
37
.env.example
Normal file
37
.env.example
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
# ─── Chrysopedia Environment Variables ───
|
||||
|
||||
# PostgreSQL
|
||||
POSTGRES_USER=chrysopedia
|
||||
POSTGRES_PASSWORD=changeme
|
||||
POSTGRES_DB=chrysopedia
|
||||
DATABASE_URL=postgresql+asyncpg://${POSTGRES_USER}:${POSTGRES_PASSWORD}@chrysopedia-db:5432/${POSTGRES_DB}
|
||||
|
||||
# Redis (Celery broker)
|
||||
REDIS_URL=redis://chrysopedia-redis:6379/0
|
||||
|
||||
# LLM endpoint (OpenAI-compatible)
|
||||
LLM_API_URL=https://friend-openwebui.example.com/api
|
||||
LLM_API_KEY=sk-changeme
|
||||
LLM_MODEL=qwen2.5-72b
|
||||
LLM_FALLBACK_URL=http://localhost:11434/v1
|
||||
LLM_FALLBACK_MODEL=qwen2.5:14b-q8_0
|
||||
|
||||
# Embedding endpoint
|
||||
EMBEDDING_API_URL=http://localhost:11434/v1
|
||||
EMBEDDING_MODEL=nomic-embed-text
|
||||
|
||||
# Qdrant
|
||||
QDRANT_URL=http://qdrant:6333
|
||||
QDRANT_COLLECTION=chrysopedia
|
||||
|
||||
# Application
|
||||
APP_ENV=production
|
||||
APP_LOG_LEVEL=info
|
||||
APP_SECRET_KEY=changeme-generate-a-real-secret
|
||||
|
||||
# File storage paths (inside container)
|
||||
TRANSCRIPT_STORAGE_PATH=/data/transcripts
|
||||
VIDEO_METADATA_PATH=/data/video_meta
|
||||
|
||||
# Review mode toggle
|
||||
REVIEW_MODE=true
|
||||
27
.gitignore
vendored
27
.gitignore
vendored
|
|
@ -4,3 +4,30 @@
|
|||
.gsd/gsd.db-wal
|
||||
.gsd/event-log.jsonl
|
||||
.gsd/state-manifest.json
|
||||
|
||||
# ── GSD baseline (auto-generated) ──
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
.idea/
|
||||
.vscode/
|
||||
*.code-workspace
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
node_modules/
|
||||
.next/
|
||||
dist/
|
||||
build/
|
||||
__pycache__/
|
||||
*.pyc
|
||||
.venv/
|
||||
venv/
|
||||
target/
|
||||
vendor/
|
||||
*.log
|
||||
coverage/
|
||||
.cache/
|
||||
tmp/
|
||||
|
|
|
|||
28
backend/main.py
Normal file
28
backend/main.py
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
"""Chrysopedia API — Knowledge extraction and retrieval system."""
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
|
||||
app = FastAPI(
|
||||
title="Chrysopedia API",
|
||||
description="Knowledge extraction and retrieval for music production content",
|
||||
version="0.1.0",
|
||||
)
|
||||
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["*"],
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
|
||||
@app.get("/health")
|
||||
async def health_check():
|
||||
return {"status": "ok", "service": "chrysopedia-api"}
|
||||
|
||||
|
||||
@app.get("/api/v1/health")
|
||||
async def api_health():
|
||||
return {"status": "ok", "version": "0.1.0"}
|
||||
11
backend/requirements.txt
Normal file
11
backend/requirements.txt
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
fastapi>=0.115.0,<1.0
|
||||
uvicorn[standard]>=0.32.0,<1.0
|
||||
sqlalchemy[asyncio]>=2.0,<3.0
|
||||
asyncpg>=0.30.0,<1.0
|
||||
alembic>=1.14.0,<2.0
|
||||
pydantic>=2.0,<3.0
|
||||
pydantic-settings>=2.0,<3.0
|
||||
celery[redis]>=5.4.0,<6.0
|
||||
redis>=5.0,<6.0
|
||||
python-dotenv>=1.0,<2.0
|
||||
httpx>=0.27.0,<1.0
|
||||
42
config/canonical_tags.yaml
Normal file
42
config/canonical_tags.yaml
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
# Canonical tags — 6 top-level production categories
|
||||
# Sub-topics grow organically during pipeline extraction
|
||||
categories:
|
||||
- name: Sound design
|
||||
description: Creating and shaping sounds from scratch or samples
|
||||
sub_topics: [bass, drums, kick, snare, hi-hat, percussion, pads, leads, fx, foley, vocals, textures]
|
||||
|
||||
- name: Mixing
|
||||
description: Balancing, processing, and spatializing elements
|
||||
sub_topics: [eq, compression, bus processing, reverb, delay, stereo imaging, gain staging, automation]
|
||||
|
||||
- name: Synthesis
|
||||
description: Methods of generating sound
|
||||
sub_topics: [fm, wavetable, granular, additive, subtractive, modular, physical modeling]
|
||||
|
||||
- name: Arrangement
|
||||
description: Structuring a track from intro to outro
|
||||
sub_topics: [song structure, transitions, tension, energy flow, breakdowns, drops]
|
||||
|
||||
- name: Workflow
|
||||
description: Creative process, session management, productivity
|
||||
sub_topics: [daw setup, templates, creative process, collaboration, file management, resampling]
|
||||
|
||||
- name: Mastering
|
||||
description: Final stage processing for release
|
||||
sub_topics: [limiting, stereo width, loudness, format delivery, referencing]
|
||||
|
||||
# Genre taxonomy (assigned to Creators, not techniques)
|
||||
genres:
|
||||
- Bass music
|
||||
- Drum & bass
|
||||
- Dubstep
|
||||
- Halftime
|
||||
- House
|
||||
- Techno
|
||||
- IDM
|
||||
- Glitch
|
||||
- Downtempo
|
||||
- Neuro
|
||||
- Ambient
|
||||
- Experimental
|
||||
- Cinematic
|
||||
113
docker-compose.yml
Normal file
113
docker-compose.yml
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
# Chrysopedia — Docker Compose
|
||||
# XPLTD convention: xpltd_chrysopedia project, bind mounts, dedicated bridge
|
||||
name: xpltd_chrysopedia
|
||||
|
||||
services:
|
||||
# ── PostgreSQL 16 ──
|
||||
chrysopedia-db:
|
||||
image: postgres:16-alpine
|
||||
container_name: chrysopedia-db
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_USER: ${POSTGRES_USER:-chrysopedia}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD required}
|
||||
POSTGRES_DB: ${POSTGRES_DB:-chrysopedia}
|
||||
volumes:
|
||||
- /vmPool/r/services/chrysopedia_db:/var/lib/postgresql/data
|
||||
ports:
|
||||
- "127.0.0.1:5433:5432"
|
||||
networks:
|
||||
- chrysopedia
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-chrysopedia}"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
# ── Redis (Celery broker) ──
|
||||
chrysopedia-redis:
|
||||
image: redis:7-alpine
|
||||
container_name: chrysopedia-redis
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- /vmPool/r/services/chrysopedia_redis:/data
|
||||
networks:
|
||||
- chrysopedia
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
# ── FastAPI application ──
|
||||
chrysopedia-api:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: docker/Dockerfile.api
|
||||
container_name: chrysopedia-api
|
||||
restart: unless-stopped
|
||||
env_file:
|
||||
- path: .env
|
||||
required: false
|
||||
environment:
|
||||
DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-chrysopedia}:${POSTGRES_PASSWORD}@chrysopedia-db:5432/${POSTGRES_DB:-chrysopedia}
|
||||
REDIS_URL: redis://chrysopedia-redis:6379/0
|
||||
volumes:
|
||||
- ./backend:/app
|
||||
- /vmPool/r/services/chrysopedia_data:/data
|
||||
ports:
|
||||
- "127.0.0.1:8000:8000"
|
||||
depends_on:
|
||||
chrysopedia-db:
|
||||
condition: service_healthy
|
||||
chrysopedia-redis:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- chrysopedia
|
||||
|
||||
# ── Celery worker (pipeline stages 2-5) ──
|
||||
chrysopedia-worker:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: docker/Dockerfile.api
|
||||
container_name: chrysopedia-worker
|
||||
restart: unless-stopped
|
||||
env_file:
|
||||
- path: .env
|
||||
required: false
|
||||
environment:
|
||||
DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-chrysopedia}:${POSTGRES_PASSWORD}@chrysopedia-db:5432/${POSTGRES_DB:-chrysopedia}
|
||||
REDIS_URL: redis://chrysopedia-redis:6379/0
|
||||
command: ["celery", "-A", "worker", "worker", "--loglevel=info"]
|
||||
volumes:
|
||||
- ./backend:/app
|
||||
- /vmPool/r/services/chrysopedia_data:/data
|
||||
- ./prompts:/prompts:ro
|
||||
depends_on:
|
||||
chrysopedia-db:
|
||||
condition: service_healthy
|
||||
chrysopedia-redis:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- chrysopedia
|
||||
|
||||
# ── React web UI (nginx) ──
|
||||
chrysopedia-web:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: docker/Dockerfile.web
|
||||
container_name: chrysopedia-web
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "127.0.0.1:3000:80"
|
||||
depends_on:
|
||||
- chrysopedia-api
|
||||
networks:
|
||||
- chrysopedia
|
||||
|
||||
networks:
|
||||
chrysopedia:
|
||||
driver: bridge
|
||||
ipam:
|
||||
config:
|
||||
- subnet: 172.24.0.0/24
|
||||
19
docker/Dockerfile.api
Normal file
19
docker/Dockerfile.api
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
FROM python:3.12-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# System deps
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
gcc libpq-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Python deps (cached layer)
|
||||
COPY backend/requirements.txt /app/requirements.txt
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# Application code
|
||||
COPY backend/ /app/
|
||||
|
||||
EXPOSE 8000
|
||||
|
||||
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
|
||||
16
docker/Dockerfile.web
Normal file
16
docker/Dockerfile.web
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
FROM node:22-alpine AS build
|
||||
|
||||
WORKDIR /app
|
||||
COPY frontend/package*.json ./
|
||||
RUN npm ci --ignore-scripts
|
||||
COPY frontend/ .
|
||||
RUN npm run build
|
||||
|
||||
FROM nginx:1.27-alpine
|
||||
|
||||
COPY --from=build /app/dist /usr/share/nginx/html
|
||||
COPY docker/nginx.conf /etc/nginx/conf.d/default.conf
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
24
docker/nginx.conf
Normal file
24
docker/nginx.conf
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
root /usr/share/nginx/html;
|
||||
index index.html;
|
||||
|
||||
# SPA fallback
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
# API proxy
|
||||
location /api/ {
|
||||
proxy_pass http://chrysopedia-api:8000;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
location /health {
|
||||
proxy_pass http://chrysopedia-api:8000;
|
||||
}
|
||||
}
|
||||
10
frontend/package.json
Normal file
10
frontend/package.json
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"name": "chrysopedia-web",
|
||||
"private": true,
|
||||
"version": "0.1.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "echo 'placeholder — install a framework first'",
|
||||
"build": "echo 'placeholder build' && mkdir -p dist && echo '<!DOCTYPE html><html><head><title>Chrysopedia</title></head><body><h1>Chrysopedia</h1><p>Web UI placeholder</p></body></html>' > dist/index.html"
|
||||
}
|
||||
}
|
||||
2
prompts/README.md
Normal file
2
prompts/README.md
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
# Prompt templates for LLM pipeline stages
|
||||
# These files are bind-mounted read-only into the worker container.
|
||||
3
whisper/README.md
Normal file
3
whisper/README.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Chrysopedia — Whisper Transcription
|
||||
|
||||
Desktop transcription script. See `transcribe.py` for usage.
|
||||
Loading…
Add table
Reference in a new issue