ciyidogan commited on
Commit
6cf7b79
·
verified ·
1 Parent(s): b861704

Update config_provider.py

Browse files
Files changed (1) hide show
  1. config_provider.py +107 -86
config_provider.py CHANGED
@@ -1,5 +1,5 @@
1
  """
2
- Flare – ConfigProvider (date type support)
3
  """
4
 
5
  from __future__ import annotations
@@ -26,7 +26,7 @@ class GlobalConfig(BaseModel):
26
  })
27
 
28
  # STT configurations
29
- stt_engine: str = Field("no_stt", pattern=r"^(no_stt|google|azure|amazon|gpt4o_realtime)$")
30
  stt_engine_api_key: Optional[str] = None
31
  stt_settings: Optional[Dict[str, Any]] = Field(default_factory=lambda: {
32
  "speech_timeout_ms": 2000,
@@ -141,28 +141,11 @@ class APIAuthConfig(BaseModel):
141
  token_refresh_endpoint: Optional[HttpUrl] = None
142
  token_refresh_body: Dict[str, Any] = {}
143
 
144
- @field_validator('token_request_body', 'token_refresh_body', mode='before')
145
- def parse_json_strings(cls, v):
146
- """Parse JSON strings to dict"""
147
- if isinstance(v, str):
148
- try:
149
- return json.loads(v)
150
- except json.JSONDecodeError:
151
- log(f"⚠️ Invalid JSON string in auth config: {v}")
152
- return {}
153
- return v
154
-
155
  class Config:
156
  extra = "allow"
157
  populate_by_name = True
158
 
159
 
160
- class ResponseMappingConfig(BaseModel):
161
- """Response mapping configuration"""
162
- variable_name: str = Field(..., pattern=r"^[a-z_][a-z0-9_]*$")
163
- type: str = Field(..., pattern=r"^(int|float|bool|str|date)$")
164
- json_path: str
165
-
166
  class APIConfig(BaseModel):
167
  name: str
168
  url: HttpUrl
@@ -171,33 +154,15 @@ class APIConfig(BaseModel):
171
  body_template: Dict[str, Any] = {}
172
  timeout_seconds: int = 10
173
  retry: RetryConfig = RetryConfig()
174
- proxy: Optional[Union[str, ProxyConfig]] = None
175
  auth: Optional[APIAuthConfig] = None
176
  response_prompt: Optional[str] = None
177
- response_mappings: List[ResponseMappingConfig] = [] # Yeni alan
178
-
179
- # Audit fields
180
- last_update_date: Optional[str] = None
181
- last_update_user: Optional[str] = None
182
- created_date: Optional[str] = None
183
- created_by: Optional[str] = None
184
- deleted: bool = False
185
-
186
- @field_validator('headers', 'body_template', mode='before')
187
- def parse_json_strings(cls, v):
188
- """Parse JSON strings to dict"""
189
- if isinstance(v, str):
190
- try:
191
- return json.loads(v)
192
- except json.JSONDecodeError:
193
- log(f"⚠️ Invalid JSON string in API config: {v}")
194
- return {}
195
- return v
196
 
197
  class Config:
198
  extra = "allow"
199
  populate_by_name = True
200
 
 
201
  # ---------------- Intent / Param ---------
202
  class ParameterConfig(BaseModel):
203
  name: str
@@ -243,22 +208,12 @@ class LLMConfig(BaseModel):
243
 
244
 
245
  class VersionConfig(BaseModel):
246
- id: int
247
- version_number: int
248
  caption: Optional[str] = ""
249
  published: bool = False
250
  general_prompt: str
251
- llm: LLMConfig
252
- intents: List[IntentConfig]
253
-
254
- # Audit fields
255
- last_update_date: Optional[str] = None
256
- last_update_user: Optional[str] = None
257
- created_date: Optional[str] = None
258
- created_by: Optional[str] = None
259
- deleted: bool = False
260
- publish_date: Optional[str] = None
261
- published_by: Optional[str] = None
262
 
263
  class Config:
264
  extra = "allow"
@@ -269,22 +224,9 @@ class ProjectConfig(BaseModel):
269
  id: Optional[int] = None
270
  name: str
271
  caption: Optional[str] = ""
272
- icon: Optional[str] = "folder"
273
- description: Optional[str] = ""
274
  enabled: bool = True
275
- default_language: str = "Turkish"
276
- supported_languages: List[str] = Field(default_factory=lambda: ["tr"])
277
- timezone: str = "Europe/Istanbul"
278
- region: str = "tr-TR"
279
- version_id_counter: int = 1
280
  versions: List[VersionConfig]
281
-
282
- # Audit fields
283
- last_update_date: Optional[str] = None
284
- last_update_user: Optional[str] = None
285
- created_date: Optional[str] = None
286
- created_by: Optional[str] = None
287
- deleted: bool = False
288
 
289
  class Config:
290
  extra = "allow"
@@ -292,9 +234,8 @@ class ProjectConfig(BaseModel):
292
 
293
  # ---------------- Activity Log -----------
294
  class ActivityLogEntry(BaseModel):
295
- id: int
296
  timestamp: str
297
- user: str
298
  action: str
299
  entity_type: str
300
  entity_id: Optional[int] = None
@@ -368,6 +309,27 @@ class ConfigProvider:
368
  cls._check_environment_setup()
369
  return cls._instance
370
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
371
  @classmethod
372
  def _load(cls) -> ServiceConfig:
373
  """Load configuration from service_config.jsonc"""
@@ -380,6 +342,62 @@ class ConfigProvider:
380
  with open(cls._CONFIG_PATH, 'r', encoding='utf-8') as f:
381
  config_data = commentjson.load(f)
382
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
383
  # Create ServiceConfig instance
384
  service_config = ServiceConfig(**config_data)
385
 
@@ -417,23 +435,26 @@ class ConfigProvider:
417
 
418
  if missing_secrets:
419
  log(f"⚠️ Running in {config.work_mode} mode. Missing secrets: {', '.join(missing_secrets)}")
420
- log("📌 Add these in HuggingFace Space Settings Repository secrets")
421
- else:
422
- log(f"✅ Running in {config.work_mode} mode with all required secrets")
423
-
424
- elif config.is_on_premise():
425
  # On-premise mode - check for .env file
426
- env_path = Path(".env")
427
- if env_path.exists():
428
- from dotenv import load_dotenv
429
- load_dotenv()
430
- log("✅ Running in on-premise mode with .env file")
431
- else:
432
  log("⚠️ Running in on-premise mode but .env file not found")
433
- log("📌 Copy .env.example to .env and configure it")
434
-
435
- @classmethod
436
- def save(cls):
437
- """Save current configuration to file"""
438
- if cls._instance:
439
- cls._instance.save()
 
 
 
 
 
 
 
 
 
 
 
1
  """
2
+ Flare – ConfigProvider (TTS/STT support)
3
  """
4
 
5
  from __future__ import annotations
 
26
  })
27
 
28
  # STT configurations
29
+ stt_engine: str = Field("no_stt", pattern=r"^(no_stt|google|azure|amazon|gpt4o_realtime|flicker)$")
30
  stt_engine_api_key: Optional[str] = None
31
  stt_settings: Optional[Dict[str, Any]] = Field(default_factory=lambda: {
32
  "speech_timeout_ms": 2000,
 
141
  token_refresh_endpoint: Optional[HttpUrl] = None
142
  token_refresh_body: Dict[str, Any] = {}
143
 
 
 
 
 
 
 
 
 
 
 
 
144
  class Config:
145
  extra = "allow"
146
  populate_by_name = True
147
 
148
 
 
 
 
 
 
 
149
  class APIConfig(BaseModel):
150
  name: str
151
  url: HttpUrl
 
154
  body_template: Dict[str, Any] = {}
155
  timeout_seconds: int = 10
156
  retry: RetryConfig = RetryConfig()
157
+ proxy: Optional[str | ProxyConfig] = None
158
  auth: Optional[APIAuthConfig] = None
159
  response_prompt: Optional[str] = None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
 
161
  class Config:
162
  extra = "allow"
163
  populate_by_name = True
164
 
165
+
166
  # ---------------- Intent / Param ---------
167
  class ParameterConfig(BaseModel):
168
  name: str
 
208
 
209
 
210
  class VersionConfig(BaseModel):
211
+ id: int = Field(..., alias="version_number")
 
212
  caption: Optional[str] = ""
213
  published: bool = False
214
  general_prompt: str
215
+ llm: "LLMConfig"
216
+ intents: List["IntentConfig"]
 
 
 
 
 
 
 
 
 
217
 
218
  class Config:
219
  extra = "allow"
 
224
  id: Optional[int] = None
225
  name: str
226
  caption: Optional[str] = ""
 
 
227
  enabled: bool = True
228
+ last_version_number: Optional[int] = None
 
 
 
 
229
  versions: List[VersionConfig]
 
 
 
 
 
 
 
230
 
231
  class Config:
232
  extra = "allow"
 
234
 
235
  # ---------------- Activity Log -----------
236
  class ActivityLogEntry(BaseModel):
 
237
  timestamp: str
238
+ username: str
239
  action: str
240
  entity_type: str
241
  entity_id: Optional[int] = None
 
309
  cls._check_environment_setup()
310
  return cls._instance
311
 
312
+ @classmethod
313
+ def reload(cls) -> ServiceConfig:
314
+ """Force reload configuration from file"""
315
+ cls._instance = None
316
+ return cls.get()
317
+
318
+ @classmethod
319
+ def update_config(cls, config_dict: dict):
320
+ """Update the current configuration with new values"""
321
+ if cls._instance is None:
322
+ cls.get()
323
+
324
+ # Update global config
325
+ if 'config' in config_dict:
326
+ for key, value in config_dict['config'].items():
327
+ if hasattr(cls._instance.global_config, key):
328
+ setattr(cls._instance.global_config, key, value)
329
+
330
+ # Save to file
331
+ cls._instance.save()
332
+
333
  @classmethod
334
  def _load(cls) -> ServiceConfig:
335
  """Load configuration from service_config.jsonc"""
 
342
  with open(cls._CONFIG_PATH, 'r', encoding='utf-8') as f:
343
  config_data = commentjson.load(f)
344
 
345
+ # Ensure required fields exist in config data
346
+ if 'config' not in config_data:
347
+ config_data['config'] = {}
348
+
349
+ config_section = config_data['config']
350
+
351
+ # Set defaults for missing fields
352
+ config_section.setdefault('work_mode', 'hfcloud')
353
+ config_section.setdefault('spark_endpoint', 'http://localhost:7861')
354
+ config_section.setdefault('cloud_token', None)
355
+ config_section.setdefault('internal_prompt', None)
356
+ config_section.setdefault('tts_engine', 'no_tts')
357
+ config_section.setdefault('tts_engine_api_key', None)
358
+ config_section.setdefault('tts_settings', {'use_ssml': False})
359
+ config_section.setdefault('stt_engine', 'no_stt')
360
+ config_section.setdefault('stt_engine_api_key', None)
361
+ config_section.setdefault('stt_settings', {
362
+ 'speech_timeout_ms': 2000,
363
+ 'noise_reduction_level': 2,
364
+ 'vad_sensitivity': 0.5,
365
+ 'language': 'tr-TR',
366
+ 'model': 'latest_long',
367
+ 'use_enhanced': True,
368
+ 'enable_punctuation': True,
369
+ 'interim_results': True
370
+ })
371
+ config_section.setdefault('users', [])
372
+
373
+ # Convert string body/headers to dict if needed
374
+ for api in config_data.get('apis', []):
375
+ if isinstance(api.get('headers'), str):
376
+ try:
377
+ api['headers'] = json.loads(api['headers'])
378
+ except:
379
+ api['headers'] = {}
380
+
381
+ if isinstance(api.get('body_template'), str):
382
+ try:
383
+ api['body_template'] = json.loads(api['body_template'])
384
+ except:
385
+ api['body_template'] = {}
386
+
387
+ # Handle auth section
388
+ if api.get('auth'):
389
+ auth = api['auth']
390
+ if isinstance(auth.get('token_request_body'), str):
391
+ try:
392
+ auth['token_request_body'] = json.loads(auth['token_request_body'])
393
+ except:
394
+ auth['token_request_body'] = {}
395
+ if isinstance(auth.get('token_refresh_body'), str):
396
+ try:
397
+ auth['token_refresh_body'] = json.loads(auth['token_refresh_body'])
398
+ except:
399
+ auth['token_refresh_body'] = {}
400
+
401
  # Create ServiceConfig instance
402
  service_config = ServiceConfig(**config_data)
403
 
 
435
 
436
  if missing_secrets:
437
  log(f"⚠️ Running in {config.work_mode} mode. Missing secrets: {', '.join(missing_secrets)}")
438
+ log("Please set these as HuggingFace Space Secrets for cloud deployment.")
439
+ else:
 
 
 
440
  # On-premise mode - check for .env file
441
+ env_path = Path(__file__).parent / ".env"
442
+ if not env_path.exists():
 
 
 
 
443
  log("⚠️ Running in on-premise mode but .env file not found")
444
+ log("Creating default .env file...")
445
+
446
+ default_env = """# Flare Environment Configuration
447
+ JWT_SECRET=flare-admin-secret-key-change-in-production
448
+ JWT_ALGORITHM=HS256
449
+ JWT_EXPIRATION_HOURS=24
450
+ FLARE_TOKEN_KEY=flare-token-encryption-key
451
+ SPARK_TOKEN=your-spark-token-here
452
+ """
453
+ env_path.write_text(default_env)
454
+ log("✅ Default .env file created. Please update with your actual values.")
455
+
456
+
457
+ # Forward references
458
+ GlobalConfig.model_rebuild()
459
+ VersionConfig.model_rebuild()
460
+ ServiceConfig.model_rebuild()