nothex commited on
Commit
723ce57
·
1 Parent(s): 67a6408

fix: deployment readiness — auth, naming, Dockerfile, render config

Browse files
Dockerfile CHANGED
@@ -29,9 +29,9 @@ COPY --chown=user:user . .
29
 
30
  # 7. Pre-build ML assets (downloads models to cache, trains intent classifier)
31
  ARG PREBUILD_ML_ASSETS=1
32
- ARG NEXUS_BUILD_ASSETS_MODE=light
33
  RUN if [ "$PREBUILD_ML_ASSETS" = "1" ]; then \
34
- NEXUS_BUILD_ASSETS_MODE=$NEXUS_BUILD_ASSETS_MODE python -m backend.core.build_ml_assets ; \
35
  else \
36
  echo "Skipping ML asset pre-build"; \
37
  fi
 
29
 
30
  # 7. Pre-build ML assets (downloads models to cache, trains intent classifier)
31
  ARG PREBUILD_ML_ASSETS=1
32
+ ARG MORPHEUS_BUILD_ASSETS_MODE=light
33
  RUN if [ "$PREBUILD_ML_ASSETS" = "1" ]; then \
34
+ MORPHEUS_BUILD_ASSETS_MODE=$MORPHEUS_BUILD_ASSETS_MODE python -m backend.core.build_ml_assets ; \
35
  else \
36
  echo "Skipping ML asset pre-build"; \
37
  fi
backend/api/admin.py CHANGED
@@ -7,7 +7,7 @@ from backend.core.warmup_classifier import warmup, warmup_cross_encoder
7
  from datetime import datetime, timedelta, timezone
8
  from collections import Counter
9
 
10
- log = logging.getLogger("nexus.api.admin")
11
  router = APIRouter()
12
 
13
 
 
7
  from datetime import datetime, timedelta, timezone
8
  from collections import Counter
9
 
10
+ log = logging.getLogger("morpheus.api.admin")
11
  router = APIRouter()
12
 
13
 
backend/api/corpus.py CHANGED
@@ -14,7 +14,7 @@ from shared.types import (
14
  CorpusFile, CorpusResponse, RenameRequest,
15
  )
16
 
17
- log = logging.getLogger("nexus.api.corpus")
18
  router = APIRouter()
19
 
20
 
 
14
  CorpusFile, CorpusResponse, RenameRequest,
15
  )
16
 
17
+ log = logging.getLogger("morpheus.api.corpus")
18
  router = APIRouter()
19
 
20
 
backend/api/ingest.py CHANGED
@@ -6,7 +6,7 @@ from backend.core.auth_utils import require_auth_token
6
  from backend.core.tasks import process_pdf_task
7
  from backend.core.tasks import celery_app
8
 
9
- log = logging.getLogger("nexus.api.ingest")
10
  router = APIRouter()
11
 
12
 
 
6
  from backend.core.tasks import process_pdf_task
7
  from backend.core.tasks import celery_app
8
 
9
+ log = logging.getLogger("morpheus.api.ingest")
10
  router = APIRouter()
11
 
12
 
backend/api/query.py CHANGED
@@ -9,7 +9,7 @@ from backend.core.pipeline import retrieve_chunks, generate_answer_stream, analy
9
  from backend.core.auth_utils import require_auth_token
10
  from backend.main import limiter
11
 
12
- log = logging.getLogger("nexus.api.query")
13
  router = APIRouter()
14
 
15
 
 
9
  from backend.core.auth_utils import require_auth_token
10
  from backend.main import limiter
11
 
12
+ log = logging.getLogger("morpheus.api.query")
13
  router = APIRouter()
14
 
15
 
backend/core/build_ml_assets.py CHANGED
@@ -11,7 +11,7 @@ import os
11
  import logging
12
 
13
  logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
14
- log = logging.getLogger("nexus.build_assets")
15
 
16
  def build_assets():
17
  log.info("Starting ML asset pre-build...")
@@ -19,14 +19,14 @@ def build_assets():
19
  # Build-time safety:
20
  # Prevent intent_classifier singleton from starting background bootstrap
21
  # threads while we run deterministic synchronous training below.
22
- os.environ["NEXUS_DISABLE_INTENT_BOOTSTRAP"] = "true"
23
 
24
  # In CI/build environments we may not have real Supabase credentials.
25
  # Keep train/upload logic local-only in that case.
26
  os.environ.setdefault("SUPABASE_URL", "")
27
  os.environ.setdefault("SUPABASE_SERVICE_KEY", "")
28
 
29
- mode = os.getenv("NEXUS_BUILD_ASSETS_MODE", "light").strip().lower()
30
  log.info("Build asset mode: %s", mode)
31
 
32
  # 1. Optional pre-download sentence-transformers (used by Intent Classifier)
 
11
  import logging
12
 
13
  logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
14
+ log = logging.getLogger("morpheus.build_assets")
15
 
16
  def build_assets():
17
  log.info("Starting ML asset pre-build...")
 
19
  # Build-time safety:
20
  # Prevent intent_classifier singleton from starting background bootstrap
21
  # threads while we run deterministic synchronous training below.
22
+ os.environ["MORPHEUS_DISABLE_INTENT_BOOTSTRAP"] = "true"
23
 
24
  # In CI/build environments we may not have real Supabase credentials.
25
  # Keep train/upload logic local-only in that case.
26
  os.environ.setdefault("SUPABASE_URL", "")
27
  os.environ.setdefault("SUPABASE_SERVICE_KEY", "")
28
 
29
+ mode = os.getenv("MORPHEUS_BUILD_ASSETS_MODE", "light").strip().lower()
30
  log.info("Build asset mode: %s", mode)
31
 
32
  # 1. Optional pre-download sentence-transformers (used by Intent Classifier)
backend/core/config.py CHANGED
@@ -29,7 +29,7 @@ COHERE_API_KEY = os.getenv("COHERE_API_KEY")
29
  MASTER_ADMIN_KEY = os.getenv("MASTER_ADMIN_KEY")
30
 
31
  # ==================== PROVIDER SELECTION ====================
32
- LLM_PROVIDER = os.getenv("NEXUS_LLM_PROVIDER", "openrouter").strip().lower()
33
  OLLAMA_BASE_URL = os.getenv("OLLAMA_BASE_URL", "http://localhost:11434")
34
  OLLAMA_MODELS = ["llama3.2", "mistral"]
35
 
 
29
  MASTER_ADMIN_KEY = os.getenv("MASTER_ADMIN_KEY")
30
 
31
  # ==================== PROVIDER SELECTION ====================
32
+ LLM_PROVIDER = os.getenv("MORPHEUS_LLM_PROVIDER", "openrouter").strip().lower()
33
  OLLAMA_BASE_URL = os.getenv("OLLAMA_BASE_URL", "http://localhost:11434")
34
  OLLAMA_MODELS = ["llama3.2", "mistral"]
35
 
backend/core/distill_reranker.py CHANGED
@@ -23,11 +23,10 @@ you can optionally promote the local model to Path 1 and make Cohere the fallbac
23
 
24
  import os
25
  import logging
26
- import json
27
  from dotenv import load_dotenv
28
 
29
  load_dotenv()
30
- log = logging.getLogger("nexus.distill")
31
  logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
32
 
33
  DISTILLED_MODEL_PATH = "backend/core/local_reranker"
 
23
 
24
  import os
25
  import logging
 
26
  from dotenv import load_dotenv
27
 
28
  load_dotenv()
29
+ log = logging.getLogger("morpheus.distill")
30
  logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
31
 
32
  DISTILLED_MODEL_PATH = "backend/core/local_reranker"
backend/core/intent_classifier.py CHANGED
@@ -31,12 +31,14 @@ from pathlib import Path
31
  from typing import Optional
32
  from supabase.client import create_client
33
 
34
- log = logging.getLogger("nexus.intent")
35
 
36
 
37
  def _bootstrap_disabled() -> bool:
38
  from backend.core import config
39
- force_disabled = os.getenv("NEXUS_DISABLE_INTENT_BOOTSTRAP", "false").lower() in {"1", "true", "yes"}
 
 
40
  # Default production-safe posture: do not train on import unless explicitly enabled.
41
  return force_disabled or (not config.INTENT_BOOTSTRAP_ON_STARTUP)
42
 
@@ -326,7 +328,9 @@ class IntentClassifier:
326
  log.info("No intent model found — will use fallback until trained.")
327
  self._ready = False
328
  if _bootstrap_disabled():
329
- log.info("Intent bootstrap disabled by NEXUS_DISABLE_INTENT_BOOTSTRAP.")
 
 
330
  elif not getattr(self, "_bootstrap_started", False):
331
  self._bootstrap_started = True
332
  threading.Thread(target=train_initial_model, daemon=True).start()
 
31
  from typing import Optional
32
  from supabase.client import create_client
33
 
34
+ log = logging.getLogger("morpheus.intent")
35
 
36
 
37
  def _bootstrap_disabled() -> bool:
38
  from backend.core import config
39
+ force_disabled = os.getenv(
40
+ "MORPHEUS_DISABLE_INTENT_BOOTSTRAP", "false"
41
+ ).lower() in {"1", "true", "yes"}
42
  # Default production-safe posture: do not train on import unless explicitly enabled.
43
  return force_disabled or (not config.INTENT_BOOTSTRAP_ON_STARTUP)
44
 
 
328
  log.info("No intent model found — will use fallback until trained.")
329
  self._ready = False
330
  if _bootstrap_disabled():
331
+ log.info(
332
+ "Intent bootstrap disabled by MORPHEUS_DISABLE_INTENT_BOOTSTRAP."
333
+ )
334
  elif not getattr(self, "_bootstrap_started", False):
335
  self._bootstrap_started = True
336
  threading.Thread(target=train_initial_model, daemon=True).start()
backend/core/tasks.py CHANGED
@@ -5,11 +5,7 @@ from backend.core.pipeline import run_ingestion
5
  # Initialize Celery pointing to your Redis broker
6
  REDIS_URL = os.getenv("REDIS_URL", "redis://localhost:6379/0")
7
 
8
- celery_app = Celery(
9
- "nexus_worker",
10
- broker=REDIS_URL,
11
- backend=REDIS_URL
12
- )
13
 
14
  @celery_app.task(bind=True)
15
  def process_pdf_task(self, tmp_path: str, original_filename: str, access_token: str):
 
5
  # Initialize Celery pointing to your Redis broker
6
  REDIS_URL = os.getenv("REDIS_URL", "redis://localhost:6379/0")
7
 
8
+ celery_app = Celery("morpheus_worker", broker=REDIS_URL, backend=REDIS_URL)
 
 
 
 
9
 
10
  @celery_app.task(bind=True)
11
  def process_pdf_task(self, tmp_path: str, original_filename: str, access_token: str):
backend/eval/run_eval.py CHANGED
@@ -36,7 +36,7 @@ from backend.core.pipeline import retrieve_chunks
36
  from backend.eval.metrics import score_example, _doc_text_for_scoring
37
  from backend.eval.openrouter_eval import ModelOrchestrator
38
 
39
- log = logging.getLogger("nexus.eval.run")
40
  logging.basicConfig(level=logging.INFO, format="%(levelname)s %(name)s — %(message)s")
41
 
42
  # Calibration: relevance_proxy must stay BELOW this for unanswerable questions
 
36
  from backend.eval.metrics import score_example, _doc_text_for_scoring
37
  from backend.eval.openrouter_eval import ModelOrchestrator
38
 
39
+ log = logging.getLogger("morpheus.eval.run")
40
  logging.basicConfig(level=logging.INFO, format="%(levelname)s %(name)s — %(message)s")
41
 
42
  # Calibration: relevance_proxy must stay BELOW this for unanswerable questions
docs/model_migration_roadmap.md CHANGED
@@ -1,4 +1,4 @@
1
- # NEXUS Model Migration Roadmap (Prototype -> Enterprise)
2
 
3
  ## Step 0: Preserve vector schema compatibility
4
  - Do not change embedding dimensions in `public.documents.embedding` until you are ready for a full re-embed migration.
@@ -7,8 +7,8 @@
7
  ## Step 1: Switch generation to a local provider (Ollama)
8
  What’s implemented:
9
  - Generation calls in `backend/core/pipeline.py` now support a provider toggle:
10
- - `NEXUS_LLM_PROVIDER=openrouter` (default)
11
- - `NEXUS_LLM_PROVIDER=ollama`
12
  - Ollama models are configured via:
13
  - `OLLAMA_MODELS` (comma-separated) or `OLLAMA_MODEL` (single model)
14
  - `OLLAMA_BASE_URL` (defaults to `http://localhost:11434`)
@@ -16,7 +16,7 @@ What’s implemented:
16
  How to run:
17
  1. Ensure Ollama is running locally and can load your target model.
18
  2. Set environment variables:
19
- - `NEXUS_LLM_PROVIDER=ollama`
20
  - `OLLAMA_MODELS=llama3`
21
 
22
  Notes:
 
1
+ # MORPHEUS Model Migration Roadmap (Prototype -> Enterprise)
2
 
3
  ## Step 0: Preserve vector schema compatibility
4
  - Do not change embedding dimensions in `public.documents.embedding` until you are ready for a full re-embed migration.
 
7
  ## Step 1: Switch generation to a local provider (Ollama)
8
  What’s implemented:
9
  - Generation calls in `backend/core/pipeline.py` now support a provider toggle:
10
+ - `MORPHEUS_LLM_PROVIDER=openrouter` (default)
11
+ - `MORPHEUS_LLM_PROVIDER=ollama`
12
  - Ollama models are configured via:
13
  - `OLLAMA_MODELS` (comma-separated) or `OLLAMA_MODEL` (single model)
14
  - `OLLAMA_BASE_URL` (defaults to `http://localhost:11434`)
 
16
  How to run:
17
  1. Ensure Ollama is running locally and can load your target model.
18
  2. Set environment variables:
19
+ - `MORPHEUS_LLM_PROVIDER=ollama`
20
  - `OLLAMA_MODELS=llama3`
21
 
22
  Notes:
vercel.json CHANGED
@@ -1,6 +1,6 @@
1
  {
2
  "version": 2,
3
- "name": "nexus-frontend",
4
  "builds": [{ "src": "frontend/**", "use": "@vercel/static" }],
5
  "routes": [{ "src": "/(.*)", "dest": "frontend/$1" }]
6
  }
 
1
  {
2
  "version": 2,
3
+ "name": "morpheus-frontend",
4
  "builds": [{ "src": "frontend/**", "use": "@vercel/static" }],
5
  "routes": [{ "src": "/(.*)", "dest": "frontend/$1" }]
6
  }