| from __future__ import annotations |
|
|
| import os |
| from pathlib import Path |
| from typing import Literal |
| from urllib.parse import urlparse |
|
|
| from pydantic import BaseModel, ConfigDict, Field, SecretStr, model_validator |
|
|
| from .schema import ForestStyle |
|
|
|
|
| class AppConfig(BaseModel): |
| model_config = ConfigDict(extra="forbid") |
|
|
| text_backend: Literal["demo", "hf_inference", "llama_cpp", "transformers", "modal"] = "demo" |
| image_backend: Literal["demo", "flux", "hf_inference", "modal", "zerogpu"] = "demo" |
| music_backend: Literal["none", "modal"] = "none" |
| hf_text_model: str = "openbmb/MiniCPM4.1-8B" |
| transformers_text_model: str = "openbmb/MiniCPM4.1-8B" |
| hf_image_model: str = "black-forest-labs/FLUX.1-schnell" |
| llama_base_url: str = "http://127.0.0.1:8080" |
| llama_model: str = "compliment-forest-minicpm5-1b" |
| flux_model_id: str = "black-forest-labs/FLUX.1-dev" |
| flux_lora_id: str = "build-small-hackathon/compliment-forest-flux-lora" |
| modal_text_endpoint: str | None = None |
| modal_image_endpoint: str | None = None |
| modal_music_endpoint: str | None = None |
| modal_signing_key: SecretStr | None = None |
| upstream_space_url: str | None = None |
| local_files_only: bool = False |
| default_seed: int = Field(default=3407, ge=0, le=2_147_483_647) |
| default_style: ForestStyle = "surprise" |
| trace_path: Path | None = None |
|
|
| @model_validator(mode="after") |
| def validate_local_text_server(self) -> AppConfig: |
| if self.text_backend == "llama_cpp": |
| hostname = urlparse(self.llama_base_url).hostname |
| if hostname not in {"127.0.0.1", "localhost", "::1"}: |
| raise ValueError("llama.cpp model server must be local") |
| if self.text_backend == "modal": |
| if not self.modal_text_endpoint or not self.modal_signing_key: |
| raise ValueError("modal text backend requires endpoint credentials") |
| if urlparse(self.modal_text_endpoint).scheme != "https": |
| raise ValueError("modal text endpoint must use HTTPS") |
| if self.image_backend == "modal": |
| if not self.modal_image_endpoint or not self.modal_signing_key: |
| raise ValueError("modal image backend requires endpoint credentials") |
| if urlparse(self.modal_image_endpoint).scheme != "https": |
| raise ValueError("modal image endpoint must use HTTPS") |
| if self.music_backend == "modal": |
| if not self.modal_music_endpoint or not self.modal_signing_key: |
| raise ValueError("modal music backend requires endpoint credentials") |
| if urlparse(self.modal_music_endpoint).scheme != "https": |
| raise ValueError("modal music endpoint must use HTTPS") |
| if self.upstream_space_url: |
| parsed_upstream = urlparse(self.upstream_space_url) |
| if parsed_upstream.scheme != "https" or not parsed_upstream.netloc: |
| raise ValueError("upstream Space URL must use HTTPS") |
| return self |
|
|
| @classmethod |
| def from_env(cls) -> AppConfig: |
| trace_path = os.getenv("CF_TRACE_PATH") |
| hosted_space = bool(os.getenv("SPACE_ID")) |
| default_text_backend = "transformers" if hosted_space else "demo" |
| default_image_backend = "zerogpu" if hosted_space else "demo" |
| return cls( |
| text_backend=os.getenv("CF_TEXT_BACKEND", default_text_backend), |
| image_backend=os.getenv("CF_IMAGE_BACKEND", default_image_backend), |
| music_backend=os.getenv("CF_MUSIC_BACKEND", "none"), |
| hf_text_model=os.getenv( |
| "CF_HF_TEXT_MODEL", |
| "openbmb/MiniCPM4.1-8B", |
| ), |
| transformers_text_model=os.getenv( |
| "CF_TRANSFORMERS_TEXT_MODEL", |
| "openbmb/MiniCPM4.1-8B", |
| ), |
| hf_image_model=os.getenv( |
| "CF_HF_IMAGE_MODEL", |
| "black-forest-labs/FLUX.1-schnell", |
| ), |
| llama_base_url=os.getenv("CF_LLAMA_BASE_URL", "http://127.0.0.1:8080"), |
| llama_model=os.getenv( |
| "CF_LLAMA_MODEL", |
| "compliment-forest-minicpm5-1b", |
| ), |
| flux_model_id=os.getenv( |
| "CF_FLUX_MODEL_ID", |
| "black-forest-labs/FLUX.1-dev", |
| ), |
| flux_lora_id=os.getenv( |
| "CF_FLUX_LORA_ID", |
| "build-small-hackathon/compliment-forest-flux-lora", |
| ), |
| modal_text_endpoint=os.getenv("CF_MODAL_TEXT_ENDPOINT"), |
| modal_image_endpoint=os.getenv("CF_MODAL_IMAGE_ENDPOINT"), |
| modal_music_endpoint=os.getenv("CF_MODAL_MUSIC_ENDPOINT"), |
| modal_signing_key=(os.getenv("CF_MODAL_SIGNING_KEY") or os.getenv("HF_TOKEN")), |
| upstream_space_url=os.getenv("CF_UPSTREAM_SPACE_URL"), |
| local_files_only=os.getenv("CF_LOCAL_FILES_ONLY", "0") == "1", |
| default_seed=int(os.getenv("CF_DEFAULT_SEED", "3407")), |
| default_style=os.getenv("CF_DEFAULT_STYLE", "surprise"), |
| trace_path=Path(trace_path) if trace_path else None, |
| ) |
|
|