File size: 6,847 Bytes
6ca4b94
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
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()