feat: config loader with toml + env override
This commit is contained in:
@@ -0,0 +1,40 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
import os
|
||||||
|
import tomllib
|
||||||
|
from pathlib import Path
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
|
REPO_ROOT = Path(__file__).resolve().parent.parent
|
||||||
|
DEFAULT_CONFIG = REPO_ROOT / "data" / "config.toml"
|
||||||
|
DEFAULT_DB = REPO_ROOT / "data" / "chat.db"
|
||||||
|
|
||||||
|
class Settings(BaseModel):
|
||||||
|
featherless_api_key: str
|
||||||
|
featherless_base_url: str = "https://api.featherless.ai/v1"
|
||||||
|
narrative_model: str = "dphn/Dolphin-Mistral-24B-Venice-Edition"
|
||||||
|
classifier_model: str = "NousResearch/Hermes-3-Llama-3.1-8B"
|
||||||
|
classifier_fallbacks: list[str] = Field(
|
||||||
|
default_factory=lambda: [
|
||||||
|
"cognitivecomputations/dolphin-2.9.4-llama3-8b",
|
||||||
|
"mlabonne/Meta-Llama-3.1-8B-Instruct-abliterated",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
ooc_marker: str = "(("
|
||||||
|
retrieval_k: int = 4
|
||||||
|
narrative_budget_hard: int = 8000
|
||||||
|
narrative_budget_soft: int = 6000
|
||||||
|
classifier_budget_hard: int = 4000
|
||||||
|
classifier_timeout_s: float = 10.0
|
||||||
|
db_path: Path = DEFAULT_DB
|
||||||
|
data_dir: Path = REPO_ROOT / "data"
|
||||||
|
bind_host: str = "127.0.0.1"
|
||||||
|
bind_port: int = 8000
|
||||||
|
|
||||||
|
def load_settings() -> Settings:
|
||||||
|
config_path = Path(os.environ.get("CHAT_CONFIG_PATH", DEFAULT_CONFIG))
|
||||||
|
raw: dict = {}
|
||||||
|
if config_path.exists():
|
||||||
|
raw = tomllib.loads(config_path.read_text())
|
||||||
|
if "CHAT_DB_PATH" in os.environ:
|
||||||
|
raw["db_path"] = Path(os.environ["CHAT_DB_PATH"])
|
||||||
|
return Settings(**raw)
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# Copy this file to data/config.toml and fill in your API key.
|
||||||
|
featherless_api_key = "REPLACE_ME"
|
||||||
|
narrative_model = "dphn/Dolphin-Mistral-24B-Venice-Edition"
|
||||||
|
classifier_model = "NousResearch/Hermes-3-Llama-3.1-8B"
|
||||||
|
ooc_marker = "(("
|
||||||
|
retrieval_k = 4
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
import pytest
|
||||||
|
from chat.config import load_settings
|
||||||
|
|
||||||
|
def test_load_settings_reads_toml(tmp_path, monkeypatch):
|
||||||
|
cfg = tmp_path / "config.toml"
|
||||||
|
cfg.write_text("""
|
||||||
|
featherless_api_key = "sk-test"
|
||||||
|
narrative_model = "dphn/Dolphin-Mistral-24B-Venice-Edition"
|
||||||
|
classifier_model = "NousResearch/Hermes-3-Llama-3.1-8B"
|
||||||
|
ooc_marker = "(("
|
||||||
|
retrieval_k = 4
|
||||||
|
""")
|
||||||
|
monkeypatch.setenv("CHAT_CONFIG_PATH", str(cfg))
|
||||||
|
s = load_settings()
|
||||||
|
assert s.featherless_api_key == "sk-test"
|
||||||
|
assert s.narrative_model.startswith("dphn/")
|
||||||
|
assert s.retrieval_k == 4
|
||||||
|
|
||||||
|
def test_chat_db_path_env_overrides_default(tmp_path, monkeypatch):
|
||||||
|
monkeypatch.setenv("CHAT_DB_PATH", str(tmp_path / "alt.db"))
|
||||||
|
monkeypatch.setenv("CHAT_CONFIG_PATH", str(tmp_path / "config.toml"))
|
||||||
|
(tmp_path / "config.toml").write_text('featherless_api_key = "x"\n')
|
||||||
|
s = load_settings()
|
||||||
|
assert s.db_path == tmp_path / "alt.db"
|
||||||
Reference in New Issue
Block a user