- Add user-decks/ directory and USER_DECKS_DIR config for exported decks - Update export-to-sim to write to user-decks/ with static mount in lab_api - Replace import/paste UI with API-backed "My Decks" dropdown in LAN client and AI Lab, fetching from GET /api/lab/decks with source grouping - Fix GET /api/lab/decks to JOIN deck_cards for totalCards count - Fix deckgenerator: add missing DOM elements (dg-strategy-bar, dg-stats-bar, dg-card-groups) inside #dg-results, null guards on render functions, fix setLoading always hiding results - Replace gpt-oss:20b with claude-opus-4-20250514 across all files - Add user-decks/ to _BUILTIN_DECK_DIRS in deck_service.py - Enrich missing type_line from Forge card cache in DB deck path - Collapse import bar behind <details> toggle in AI Lab Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
70 lines
4.1 KiB
Python
70 lines
4.1 KiB
Python
"""
|
|
Commander AI Lab — Coach Configuration
|
|
────────────────────────────────────────
|
|
Central config for Ollama, embeddings, and coach service paths.
|
|
All paths are relative to the commander-ai-lab root directory.
|
|
"""
|
|
|
|
import os
|
|
from pathlib import Path
|
|
|
|
# ── Base Paths ───────────────────────────────────────────────────────
|
|
LAB_ROOT = Path(os.environ.get("COMMANDER_LAB_ROOT", Path(__file__).parent.parent))
|
|
|
|
# ── Ollama (OpenAI-compatible API) ────────────────────────────
|
|
LLM_URL = os.environ.get("LLM_URL", "http://localhost:11434/v1")
|
|
LLM_MODEL = os.environ.get("LLM_MODEL", "claude-opus-4-20250514")
|
|
LLM_TIMEOUT = int(os.environ.get("LLM_TIMEOUT", "360")) # seconds
|
|
LLM_MAX_RETRIES = 3
|
|
|
|
# ── Embeddings ───────────────────────────────────────────────────
|
|
EMBEDDINGS_DIR = LAB_ROOT / "data"
|
|
EMBEDDINGS_NPZ = EMBEDDINGS_DIR / "mtg-embeddings.npz"
|
|
EMBEDDINGS_PARQUET = EMBEDDINGS_DIR / "mtg-embeddings.parquet"
|
|
|
|
# ── Deck Reports ────────────────────────────────────────────────
|
|
DECK_REPORTS_DIR = LAB_ROOT / "deck-reports"
|
|
COACH_SESSIONS_DIR = LAB_ROOT / "coach-sessions"
|
|
|
|
# ── Prompt Limits ───────────────────────────────────────────────
|
|
MAX_PROMPT_TOKENS = 2048
|
|
MAX_CANDIDATES_PER_UNDERPERFORMER = 8
|
|
MAX_UNDERPERFORMERS = 8
|
|
UNDERPERFORMER_IMPACT_THRESHOLD = -0.05 # impactScore below this = underperformer
|
|
|
|
# ── LLM Generation Settings (Coach — Ollama fallback) ─────────────
|
|
DEFAULT_TEMPERATURE = 0.7
|
|
DEFAULT_MAX_TOKENS = 16384
|
|
|
|
# ── Anthropic Claude Deck Generation Settings ──────────────────────
|
|
# Provider for deck generation: "anthropic" (Claude) or "local" (Ollama)
|
|
DECK_GEN_PROVIDER = os.environ.get("DECK_GEN_PROVIDER", "anthropic")
|
|
# Model used when DECK_GEN_PROVIDER="anthropic"
|
|
DECK_GEN_MODEL = os.environ.get("DECK_GEN_MODEL", "claude-opus-4-20250514")
|
|
# Anthropic API key
|
|
ANTHROPIC_API_KEY = os.environ.get("ANTHROPIC_API_KEY", "")
|
|
# Anthropic model for deck generation and coaching
|
|
ANTHROPIC_MODEL = os.environ.get("ANTHROPIC_MODEL", "claude-opus-4-20250514")
|
|
# Coach chat provider: "anthropic" (Claude API) or "local" (Ollama)
|
|
COACH_PROVIDER = os.environ.get("COACH_PROVIDER", "anthropic")
|
|
DECK_GEN_BASE_URL = os.environ.get("DECK_GEN_BASE_URL", "http://localhost:11434/v1")
|
|
DECK_GEN_TEMPERATURE = float(os.environ.get("DECK_GEN_TEMPERATURE", "0.2"))
|
|
DECK_GEN_MAX_TOKENS = int(os.environ.get("DECK_GEN_MAX_TOKENS", "16384"))
|
|
|
|
# ── Smart Substitution Settings ───────────────────────────────────
|
|
# Minimum embedding similarity to accept a substitute without Anthropic fallback
|
|
SUBSTITUTION_MIN_SIMILARITY = float(os.environ.get("SUBSTITUTION_MIN_SIMILARITY", "0.75"))
|
|
# Maximum number of alternatives to suggest per missing card
|
|
SUBSTITUTION_MAX_ALTERNATIVES = int(os.environ.get("SUBSTITUTION_MAX_ALTERNATIVES", "5"))
|
|
# Model for substitution fallback (claude-haiku-4-5 is fast + cheap for focused queries)
|
|
SUBSTITUTION_MODEL = os.environ.get("SUBSTITUTION_MODEL", "claude-haiku-4-5")
|
|
# Enable Anthropic fallback for low-confidence embedding matches
|
|
SUBSTITUTION_USE_ANTHROPIC_FALLBACK = os.environ.get("SUBSTITUTION_USE_ANTHROPIC_FALLBACK", "true").lower() == "true"
|
|
|
|
# ── Ensure directories exist ─────────────────────────────────────
|
|
def ensure_dirs():
|
|
"""Create required directories if they don't exist."""
|
|
EMBEDDINGS_DIR.mkdir(parents=True, exist_ok=True)
|
|
DECK_REPORTS_DIR.mkdir(parents=True, exist_ok=True)
|
|
COACH_SESSIONS_DIR.mkdir(parents=True, exist_ok=True)
|