Spaces:
Running
Running
Update config_provider.py
Browse files- config_provider.py +126 -15
config_provider.py
CHANGED
@@ -1,19 +1,130 @@
|
|
1 |
-
|
2 |
-
|
3 |
-
|
|
|
|
|
|
|
|
|
4 |
|
5 |
-
|
|
|
|
|
6 |
|
7 |
-
|
8 |
-
|
9 |
-
with open(CONFIG_FILE, "r") as f:
|
10 |
-
self.data = json.load(f)
|
11 |
|
12 |
-
|
13 |
-
if not self.data['projects']:
|
14 |
-
raise ValueError("No projects configured")
|
15 |
-
# For simplicity, just return the first project
|
16 |
-
return self.data['projects'][0]
|
17 |
|
18 |
-
|
19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
Flare – Configuration Loader
|
3 |
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
4 |
+
• JSONC (comment-json) desteği
|
5 |
+
• Pydantic şema + runtime validation
|
6 |
+
• Global erişim için singleton ConfigProvider.get()
|
7 |
+
"""
|
8 |
|
9 |
+
import pathlib
|
10 |
+
from functools import lru_cache
|
11 |
+
from typing import Dict, List, Optional
|
12 |
|
13 |
+
import commentjson as jsonc
|
14 |
+
from pydantic import BaseModel, Field, validator
|
|
|
|
|
15 |
|
16 |
+
CONFIG_PATH = pathlib.Path(__file__).parent / "service_config.jsonc"
|
|
|
|
|
|
|
|
|
17 |
|
18 |
+
|
19 |
+
# === Pydantic Schemas =======================================================
|
20 |
+
class RetryConfig(BaseModel):
|
21 |
+
max_attempts: int = 3
|
22 |
+
backoff_seconds: int = 2
|
23 |
+
strategy: str = Field("static", regex="^(static|exponential)$")
|
24 |
+
|
25 |
+
|
26 |
+
class ProxyConfig(BaseModel):
|
27 |
+
enabled: bool = False
|
28 |
+
url: Optional[str] = None
|
29 |
+
|
30 |
+
|
31 |
+
class AuthConfig(BaseModel):
|
32 |
+
enabled: bool = False
|
33 |
+
token_endpoint: Optional[str] = None
|
34 |
+
body_template: Dict[str, str] = {}
|
35 |
+
response_token_path: Optional[str] = None
|
36 |
+
token_refresh_endpoint: Optional[str] = None
|
37 |
+
token_refresh_body: Dict[str, str] = {}
|
38 |
+
|
39 |
+
@validator("token_endpoint", always=True)
|
40 |
+
def _require_endpoint(cls, v, values):
|
41 |
+
if values["enabled"] and not v:
|
42 |
+
raise ValueError("Auth enabled but token_endpoint missing")
|
43 |
+
return v
|
44 |
+
|
45 |
+
|
46 |
+
class APIConfig(BaseModel):
|
47 |
+
url: str
|
48 |
+
method: str = Field("POST", regex="^(GET|POST|PUT|DELETE|PATCH)$")
|
49 |
+
headers: Dict[str, str] = {}
|
50 |
+
body_template: Dict[str, str] = {}
|
51 |
+
timeout_seconds: int = 10
|
52 |
+
retry: RetryConfig = RetryConfig()
|
53 |
+
auth: AuthConfig = AuthConfig()
|
54 |
+
proxy: ProxyConfig = ProxyConfig()
|
55 |
+
response_prompt: str
|
56 |
+
|
57 |
+
|
58 |
+
class ParameterConfig(BaseModel):
|
59 |
+
name: str
|
60 |
+
type: str
|
61 |
+
required: bool = True
|
62 |
+
extraction_prompt: str
|
63 |
+
validation_regex: Optional[str] = None
|
64 |
+
invalid_prompt: Optional[str] = None
|
65 |
+
type_error_prompt: Optional[str] = None
|
66 |
+
|
67 |
+
|
68 |
+
class IntentConfig(BaseModel):
|
69 |
+
name: str
|
70 |
+
caption: Optional[str]
|
71 |
+
locale: str = "tr-TR"
|
72 |
+
dependencies: List[str] = []
|
73 |
+
examples: List[str]
|
74 |
+
detection_prompt: str
|
75 |
+
parameters: List[ParameterConfig] = []
|
76 |
+
action: str
|
77 |
+
fallback_timeout_prompt: Optional[str] = None
|
78 |
+
fallback_error_prompt: Optional[str] = None
|
79 |
+
|
80 |
+
|
81 |
+
class LLMConfig(BaseModel):
|
82 |
+
repo_id: str
|
83 |
+
generation_config: Dict[str, float]
|
84 |
+
use_fine_tune: bool = False
|
85 |
+
fine_tune_zip: Optional[str] = None
|
86 |
+
|
87 |
+
|
88 |
+
class VersionConfig(BaseModel):
|
89 |
+
version_number: int
|
90 |
+
published: bool
|
91 |
+
general_prompt: str
|
92 |
+
llm: LLMConfig
|
93 |
+
intents: List[IntentConfig]
|
94 |
+
|
95 |
+
|
96 |
+
class ProjectConfig(BaseModel):
|
97 |
+
name: str
|
98 |
+
enabled: bool = True
|
99 |
+
last_version_number: int
|
100 |
+
versions: List[VersionConfig]
|
101 |
+
|
102 |
+
|
103 |
+
class UserConfig(BaseModel):
|
104 |
+
username: str
|
105 |
+
password_hash: str
|
106 |
+
salt: str
|
107 |
+
|
108 |
+
|
109 |
+
class GlobalConfig(BaseModel):
|
110 |
+
work_mode: str = Field(..., regex="^(hfcloud|cloud|on-premise)$")
|
111 |
+
cloud_token: Optional[str]
|
112 |
+
spark_endpoint: str
|
113 |
+
users: List[UserConfig]
|
114 |
+
|
115 |
+
|
116 |
+
class RootConfig(BaseModel):
|
117 |
+
config: GlobalConfig
|
118 |
+
projects: List[ProjectConfig]
|
119 |
+
apis: Dict[str, APIConfig]
|
120 |
+
|
121 |
+
|
122 |
+
# === Singleton Loader =======================================================
|
123 |
+
class ConfigProvider:
|
124 |
+
@staticmethod
|
125 |
+
@lru_cache
|
126 |
+
def get(path: str = None) -> RootConfig:
|
127 |
+
cfg_file = pathlib.Path(path) if path else CONFIG_PATH
|
128 |
+
with cfg_file.open("r", encoding="utf-8") as f:
|
129 |
+
data = jsonc.load(f)
|
130 |
+
return RootConfig.parse_obj(data)
|