synth-net / src /config.py
github-actions
Sync from GitHub (CI)
6ca4b94
import os
import logging
from typing import Optional
from pydantic import BaseModel, field_validator, SecretStr, field_serializer
from pydantic_settings import BaseSettings, SettingsConfigDict
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
class AppSettings(BaseModel):
name: str = "SynthNet"
id: str = "synth-net"
version: str = "0.0.1"
description: str = "The Synthetic Nomological Net: A search engine to identify conceptual overlap in measures in the behavioral sciences"
author: str = "magnolia psychometrics GmbH"
class PublicMetadata(BaseModel):
name: str = "SynthNet"
description: str = "The Synthetic Nomological Net: A search engine to identify conceptual overlap in measures in the behavioral sciences"
author: str = "magnolia psychometrics GmbH"
github_url: Optional[str] = "https://github.com/synth-science/synth-net"
osf_url: Optional[str] = "https://osf.io/h3xgw"
imprint_url: Optional[str] = "https://raw.githubusercontent.com/magnolia-psychometrics/public/refs/heads/main/imprint-en.md"
data_privacy_url: Optional[str] = "https://raw.githubusercontent.com/magnolia-psychometrics/public/refs/heads/main/imprint-en.md"
tos_url: Optional[str] = "https://github.com/magnolia-psychometrics/public/blob/main/tos-en.md"
disclaimer_url: Optional[str] = "https://github.com/magnolia-psychometrics/public/blob/main/hf-disclaimer.md"
class SearchSettings(BaseModel):
item_examples: list[list] = [
["I frequently engineer situations where I can casually roll up my pant legs to showcase my calf definition.", "My calf muscles are unremarkable and not worth drawing attention to. (R)", "I have strategically positioned mirrors in my home at angles that optimize calf muscle viewing during daily activities.", "When receiving compliments about my physique, I feel uncomfortable if someone specifically mentions my calves. (R)", "I believe my gastrocnemius and soleus development represents the pinnacle of human lower leg musculature and should be documented for posterity."],
["Receiving compliments is important to me.", "I rarely doubt my decisions or actions.", "I'm just like everybody else.(R)", "I'm skilled at persuading others to believe what I say.", "Being humble doesn't suit my personality.", "I consider myself to be truly exceptional.", "Gaining recognition and status is important to me.", "I'm destined for remarkable achievements."],
["People who claim to be lactose intolerant are simply seeking attention and making excuses to avoid social gatherings.", "I believe lactose intolerant individuals deserve the same respect and dietary accommodations as anyone else. (R)", "Lactose intolerance is a character flaw that could be overcome with sufficient willpower and determination.", "I would be willing to modify a dinner menu to ensure lactose intolerant guests can enjoy the meal comfortably. (R)", "The so-called \"lactose intolerance epidemic\" is largely fabricated by the almond milk industry to increase profits.", "I become suspicious of people's true intentions when they decline dairy products at social events."],
["Birds are sophisticated surveillance drones operated by government agencies to monitor civilian activity.", "The moon landing footage is authentic and represents humanity's genuine achievement in space exploration. (R)", "Major weather events are deliberately manufactured by shadow organizations using advanced atmospheric manipulation technology.", "Giraffes exist in nature and are not elaborate hoaxes perpetuated by zoos worldwide. (R)", "All mattress stores are fronts for money laundering operations, which explains why they're always empty yet remain in business.", "Finland is a real country with a legitimate government and population. (R)"],
]
scale_examples: list[str] = [
"calf muscle modesty", "vanity", "self-centeredness", "megalomania", "sociopathy", "galaphobia", "lactophobia", "intolerant attitudes against lactose intolerance"
]
class ModelServerSettings(BaseModel):
server_url: str = "http://localhost:8001"
item_model_path: str = None
item_model_access_token: Optional[str] = None
scale_model_path: str = None
scale_model_access_token: Optional[str] = None
device: Optional[str] = None
class DatasetSettings(BaseModel):
dataset_path: str = None
encryption_key: Optional[str] = None
class TrackingDBSettings(BaseModel):
enabled: bool = True
api_endpoint: Optional[str] = None
anon_key: Optional[SecretStr] = None
jwt_token: Optional[SecretStr] = None
class Settings(BaseSettings):
model_config = SettingsConfigDict(
env_file=".env",
env_nested_delimiter="__",
frozen=True
)
app: AppSettings = AppSettings()
public: PublicMetadata = PublicMetadata()
search: SearchSettings = SearchSettings()
model: ModelServerSettings = ModelServerSettings()
data: DatasetSettings = DatasetSettings()
tracking_db: TrackingDBSettings = TrackingDBSettings()
def validate_config(self) -> bool:
from typing import get_origin, get_args
is_valid = True
missing = []
optional_set = []
def check_model(obj: BaseModel, prefix: str = ""):
nonlocal is_valid
for field_name, field_info in obj.model_fields.items():
value = getattr(obj, field_name)
env_name = f"{prefix}{field_name}".upper()
if isinstance(value, BaseModel):
check_model(value, f"{env_name}__")
continue
annotation = field_info.annotation
is_optional = (
get_origin(annotation) is Optional or
type(None) in get_args(annotation)
)
if not is_optional and value is None:
missing.append(env_name)
is_valid = False
elif is_optional and value is not None:
optional_set.append(env_name)
check_model(self)
if missing:
logger.error(f"❌ Missing required environment variables: {', '.join(missing)}")
else:
logger.info("βœ… Config: All required environment variables loaded")
if optional_set:
logger.info(f"βœ… Config: Optional variables set: {', '.join(optional_set)}")
if not self.tracking_db.enabled:
logger.info("Tracking disabled in config / ENV, skipping DB write!")
return is_valid
config = Settings()
config.validate_config()