Merge branch 'fix/gpu-server-url-rename' into freeze/pr-12-14-15-integration
This commit is contained in:
commit
75174c40e4
6 changed files with 122 additions and 9 deletions
|
|
@ -23,10 +23,13 @@ HEIMDALL_ADMIN_TOKEN=
|
|||
# Must match COORDINATOR_PRODUCT_KEYS["pagepiper"] in cf-orch.env on the coordinator
|
||||
COORDINATOR_PAGEPIPER_KEY=
|
||||
|
||||
# cf-orch coordinator URL — routes chat/embed calls through managed GPU allocation
|
||||
# CF_LICENSE_KEY is the auth token sent to the coordinator (same value as COORDINATOR_PAGEPIPER_KEY)
|
||||
# Leave CF_ORCH_URL blank to skip allocation and hit PAGEPIPER_OLLAMA_URL directly
|
||||
CF_ORCH_URL=
|
||||
# GPU server / cf-orch coordinator URL — routes chat/embed calls through managed
|
||||
# GPU allocation. CF_LICENSE_KEY is the auth token sent to the coordinator (same
|
||||
# value as COORDINATOR_PAGEPIPER_KEY). Leave blank to skip allocation and hit
|
||||
# PAGEPIPER_OLLAMA_URL directly. CF_ORCH_URL is still honoured as a legacy alias
|
||||
# if GPU_SERVER_URL is unset — Paid+ tiers auto-default to orch.circuitforge.tech
|
||||
# when CF_LICENSE_KEY is present.
|
||||
GPU_SERVER_URL=
|
||||
CF_LICENSE_KEY=
|
||||
CF_APP_NAME=pagepiper
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,12 @@ PAGEPIPER_DATA_DIR=data
|
|||
PAGEPIPER_CHAT_MODEL=mistral:7b
|
||||
PAGEPIPER_EMBED_MODEL=nomic-embed-text
|
||||
|
||||
# Self-hosted GPU rig URL — set this instead of PAGEPIPER_OLLAMA_URL if you're
|
||||
# running a cf-orch coordinator (e.g. a home GPU rack). The coordinator resolves
|
||||
# the actual service URL at allocation time. (CF_ORCH_URL is still honoured as
|
||||
# a legacy alias if you already have it set.)
|
||||
# GPU_SERVER_URL=http://localhost:7700
|
||||
|
||||
# Forgejo API token — enables the in-app feedback button (files Forgejo issues)
|
||||
# Create a token at https://git.opensourcesolarpunk.com/user/settings/applications
|
||||
# FORGEJO_API_TOKEN=
|
||||
|
|
|
|||
|
|
@ -14,6 +14,21 @@ VEC_DIMENSIONS = int(os.environ.get("PAGEPIPER_EMBED_DIMS", "1024"))
|
|||
|
||||
LOCAL_USER_ID = "__local__"
|
||||
|
||||
CF_LICENSE_KEY = os.environ.get("CF_LICENSE_KEY")
|
||||
|
||||
# Priority: GPU_SERVER_URL env var -> CF_ORCH_URL env var (backward compat)
|
||||
# -> https://orch.circuitforge.tech when CF_LICENSE_KEY is present (Paid+)
|
||||
# Resolved value is written back to os.environ["CF_ORCH_URL"] so every existing
|
||||
# caller that reads os.environ.get("CF_ORCH_URL") directly (get_llm_config below,
|
||||
# app/api/chat.py) sees the right URL without any further changes.
|
||||
GPU_SERVER_URL = (
|
||||
os.environ.get("GPU_SERVER_URL")
|
||||
or os.environ.get("CF_ORCH_URL")
|
||||
or ("https://orch.circuitforge.tech" if CF_LICENSE_KEY else None)
|
||||
)
|
||||
if GPU_SERVER_URL:
|
||||
os.environ["CF_ORCH_URL"] = GPU_SERVER_URL
|
||||
|
||||
|
||||
def user_data_dir(user_id: str) -> Path:
|
||||
"""Return (and create) the per-user data directory under DATA_DIR/users/."""
|
||||
|
|
|
|||
|
|
@ -17,8 +17,10 @@ services:
|
|||
PAGEPIPER_BOOKS_DIR: /devl/pagepiper-cloud-data/books
|
||||
# PAGEPIPER_OLLAMA_URL — set in .env (BYOK gate for hybrid search + RAG)
|
||||
# HEIMDALL_URL, HEIMDALL_ADMIN_TOKEN — set in .env for license validation
|
||||
# cf-orch: route LLM inference through coordinator for managed GPU access
|
||||
CF_ORCH_URL: http://host.docker.internal:7700
|
||||
# GPU server: route LLM inference through the cf-orch coordinator for
|
||||
# managed GPU access (app/config.py normalizes this into CF_ORCH_URL
|
||||
# internally, so no other service code needs to change)
|
||||
GPU_SERVER_URL: http://host.docker.internal:7700
|
||||
CF_APP_NAME: pagepiper
|
||||
# CF_LICENSE_KEY is the auth token CFOrchClient sends to the coordinator
|
||||
CF_LICENSE_KEY: ${COORDINATOR_PAGEPIPER_KEY:-}
|
||||
|
|
|
|||
|
|
@ -19,12 +19,13 @@ Copy `.env.example` to `.env` and configure as needed.
|
|||
| `PAGEPIPER_EMBED_DIMS` | `1024` | Embedding dimensions (must match the model) |
|
||||
| `PAGEPIPER_CHAT_MODEL` | `mistral:7b` | Ollama chat/completion model |
|
||||
|
||||
## cf-orch (managed deployments)
|
||||
## GPU server / cf-orch (managed deployments)
|
||||
|
||||
| Variable | Default | Description |
|
||||
|----------|---------|-------------|
|
||||
| `CF_ORCH_URL` | _(unset)_ | cf-orch coordinator URL for GPU allocation |
|
||||
| `CF_LICENSE_KEY` | _(unset)_ | License key for cf-orch authentication |
|
||||
| `GPU_SERVER_URL` | _(unset)_ | Self-hosted GPU rig / cf-orch coordinator URL for GPU allocation. Preferred over `CF_ORCH_URL`. |
|
||||
| `CF_ORCH_URL` | _(unset)_ | Legacy alias for `GPU_SERVER_URL` — still honoured if `GPU_SERVER_URL` is unset. |
|
||||
| `CF_LICENSE_KEY` | _(unset)_ | License key for cf-orch authentication. When set and neither `GPU_SERVER_URL` nor `CF_ORCH_URL` is configured, defaults `GPU_SERVER_URL` to `https://orch.circuitforge.tech` (Paid+ tiers). |
|
||||
| `CF_APP_NAME` | `pagepiper` | Application identifier sent to cf-orch |
|
||||
|
||||
## License (cloud tier)
|
||||
|
|
|
|||
86
tests/test_config.py
Normal file
86
tests/test_config.py
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
# tests/test_config.py
|
||||
"""Unit tests for the GPU_SERVER_URL / CF_ORCH_URL resolution in app/config.py.
|
||||
|
||||
app/config.py resolves GPU_SERVER_URL at *module import time* (module-level
|
||||
code, not a function), so each test reloads the module after adjusting env
|
||||
vars via monkeypatch, then reloads it again afterward with the real
|
||||
environment restored so later tests see normal module state.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib
|
||||
|
||||
import pytest
|
||||
|
||||
import app.config as config
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def _restore_config_module():
|
||||
yield
|
||||
importlib.reload(config)
|
||||
|
||||
|
||||
def _clear_orch_env(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
monkeypatch.delenv("GPU_SERVER_URL", raising=False)
|
||||
monkeypatch.delenv("CF_ORCH_URL", raising=False)
|
||||
monkeypatch.delenv("CF_LICENSE_KEY", raising=False)
|
||||
|
||||
|
||||
def test_gpu_server_url_prefers_explicit_env_var(monkeypatch):
|
||||
_clear_orch_env(monkeypatch)
|
||||
monkeypatch.setenv("GPU_SERVER_URL", "http://my-rig:7700")
|
||||
monkeypatch.setenv("CF_ORCH_URL", "http://should-be-ignored:7700")
|
||||
|
||||
importlib.reload(config)
|
||||
|
||||
assert config.GPU_SERVER_URL == "http://my-rig:7700"
|
||||
|
||||
|
||||
def test_gpu_server_url_falls_back_to_cf_orch_url_legacy_alias(monkeypatch):
|
||||
_clear_orch_env(monkeypatch)
|
||||
monkeypatch.setenv("CF_ORCH_URL", "http://legacy-coordinator:7700")
|
||||
|
||||
importlib.reload(config)
|
||||
|
||||
assert config.GPU_SERVER_URL == "http://legacy-coordinator:7700"
|
||||
|
||||
|
||||
def test_gpu_server_url_defaults_when_license_key_present(monkeypatch):
|
||||
_clear_orch_env(monkeypatch)
|
||||
monkeypatch.setenv("CF_LICENSE_KEY", "test-key-123")
|
||||
|
||||
importlib.reload(config)
|
||||
|
||||
assert config.GPU_SERVER_URL == "https://orch.circuitforge.tech"
|
||||
|
||||
|
||||
def test_gpu_server_url_none_when_nothing_set(monkeypatch):
|
||||
_clear_orch_env(monkeypatch)
|
||||
|
||||
importlib.reload(config)
|
||||
|
||||
assert config.GPU_SERVER_URL is None
|
||||
|
||||
|
||||
def test_gpu_server_url_writes_back_to_cf_orch_url_for_legacy_callers(monkeypatch):
|
||||
"""get_llm_config() and app/api/chat.py read os.environ["CF_ORCH_URL"] directly —
|
||||
the write-back must happen so they keep working without code changes."""
|
||||
import os
|
||||
|
||||
_clear_orch_env(monkeypatch)
|
||||
monkeypatch.setenv("GPU_SERVER_URL", "http://my-rig:7700")
|
||||
|
||||
importlib.reload(config)
|
||||
|
||||
assert os.environ.get("CF_ORCH_URL") == "http://my-rig:7700"
|
||||
|
||||
|
||||
def test_gpu_server_url_unset_does_not_write_back(monkeypatch):
|
||||
import os
|
||||
|
||||
_clear_orch_env(monkeypatch)
|
||||
|
||||
importlib.reload(config)
|
||||
|
||||
assert "CF_ORCH_URL" not in os.environ
|
||||
Loading…
Reference in a new issue