cortex.6.sol / cortex_ai /config.py
Frankenstein-Labs's picture
feat: add founder behavioral charter
f019291
Raw History Blame Contribute Delete
5.21 kB
"""Central configuration for the CORTEX AI ecosystem.
Every runtime component reads its defaults from here so that a single
environment variable or a single JSON file can reconfigure the whole stack.
"""
from __future__ import annotations
import json
import os
from dataclasses import dataclass, field, asdict
from pathlib import Path
from typing import Any
from .behavior import FOUNDER_BEHAVIOR_PROMPT
DEFAULT_MODEL_ID = "Frankenstein-Labs/Cortex-ai"
DEFAULT_SYSTEM_PROMPT = (
FOUNDER_BEHAVIOR_PROMPT
+ "\n\n"
"Tu es CORTEX AI, un assistant développé par Frankenstein-Labs. "
"Réponds de façon précise et concise. "
"Si on te demande qui a créé ce projet, réponds que ton créateur est "
"Abdoulaye Coumbassa, un jeune créateur de 16 ans et fondateur de "
"Frankenstein-Labs, et qu'il a dit un jour que tu es son plus grand "
"chef-d'œuvre. CORTEX AI est construit sur le modèle DeepSeek-V4. "
"Cette phrase concerne le projet CORTEX AI, pas le modèle de base."
)
@dataclass
class EngineConfig:
"""Controls the agent loop."""
max_tool_rounds: int = 8
thinking_mode: str = "thinking"
reasoning_effort: str = "high"
max_new_tokens: int = 1024
temperature: float = 0.6
def __post_init__(self) -> None:
if self.thinking_mode not in ("chat", "thinking"):
raise ValueError(f"thinking_mode must be 'chat' or 'thinking', got {self.thinking_mode!r}")
if self.reasoning_effort not in ("low", "high", "max"):
raise ValueError(f"reasoning_effort must be low/high/max, got {self.reasoning_effort!r}")
if self.max_tool_rounds < 1:
raise ValueError("max_tool_rounds must be >= 1")
@dataclass
class ServerConfig:
"""Controls the HTTP API."""
host: str = "0.0.0.0"
port: int = 8000
api_key: str = ""
request_timeout_s: float = 600.0
@property
def requires_auth(self) -> bool:
return bool(self.api_key)
@dataclass
class CortexConfig:
"""Top-level configuration for a CORTEX AI deployment."""
model_id: str = DEFAULT_MODEL_ID
system_prompt: str = DEFAULT_SYSTEM_PROMPT
engine: EngineConfig = field(default_factory=EngineConfig)
server: ServerConfig = field(default_factory=ServerConfig)
enabled_tools: list[str] = field(default_factory=list)
def to_dict(self) -> dict[str, Any]:
return asdict(self)
@classmethod
def from_dict(cls, data: dict[str, Any]) -> "CortexConfig":
engine = EngineConfig(**data.get("engine", {}))
server = ServerConfig(**data.get("server", {}))
return cls(
model_id=data.get("model_id", DEFAULT_MODEL_ID),
system_prompt=data.get("system_prompt", DEFAULT_SYSTEM_PROMPT),
engine=engine,
server=server,
enabled_tools=list(data.get("enabled_tools", [])),
)
@classmethod
def from_env(cls) -> "CortexConfig":
"""Build a config from CORTEX_* environment variables."""
cfg = cls()
if v := os.getenv("CORTEX_MODEL_ID"):
cfg.model_id = v
if v := os.getenv("CORTEX_API_KEY"):
cfg.server.api_key = v
if v := os.getenv("CORTEX_PORT"):
cfg.server.port = int(v)
if v := os.getenv("CORTEX_HOST"):
cfg.server.host = v
if v := os.getenv("CORTEX_MAX_TOOL_ROUNDS"):
cfg.engine.max_tool_rounds = int(v)
if v := os.getenv("CORTEX_THINKING_MODE"):
cfg.engine.thinking_mode = v
if v := os.getenv("CORTEX_REASONING_EFFORT"):
cfg.engine.reasoning_effort = v
if v := os.getenv("CORTEX_TOOLS"):
cfg.enabled_tools = [t.strip() for t in v.split(",") if t.strip()]
return cfg
@classmethod
def load(cls, path: str | Path | None = None) -> "CortexConfig":
"""Load from a JSON file if it exists, then apply environment overrides.
Environment variables win over the file, but only when actually set:
an unset variable must not silently reset a value read from the file.
"""
cfg = cls()
if path is not None:
p = Path(path)
if p.exists():
cfg = cls.from_dict(json.loads(p.read_text(encoding="utf-8")))
env = os.environ
if v := env.get("CORTEX_MODEL_ID"):
cfg.model_id = v
if v := env.get("CORTEX_API_KEY"):
cfg.server.api_key = v
if v := env.get("CORTEX_PORT"):
cfg.server.port = int(v)
if v := env.get("CORTEX_HOST"):
cfg.server.host = v
if v := env.get("CORTEX_MAX_TOOL_ROUNDS"):
cfg.engine.max_tool_rounds = int(v)
if v := env.get("CORTEX_THINKING_MODE"):
cfg.engine.thinking_mode = v
if v := env.get("CORTEX_REASONING_EFFORT"):
cfg.engine.reasoning_effort = v
if v := env.get("CORTEX_TOOLS"):
cfg.enabled_tools = [t.strip() for t in v.split(",") if t.strip()]
return cfg
def save(self, path: str | Path) -> None:
Path(path).write_text(
json.dumps(self.to_dict(), indent=2, ensure_ascii=False), encoding="utf-8"
)