isa-model 0.3.4__py3-none-any.whl → 0.3.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. isa_model/__init__.py +30 -1
  2. isa_model/client.py +770 -0
  3. isa_model/core/config/__init__.py +16 -0
  4. isa_model/core/config/config_manager.py +514 -0
  5. isa_model/core/config.py +426 -0
  6. isa_model/core/models/model_billing_tracker.py +476 -0
  7. isa_model/core/models/model_manager.py +399 -0
  8. isa_model/core/models/model_repo.py +343 -0
  9. isa_model/core/pricing_manager.py +426 -0
  10. isa_model/core/services/__init__.py +19 -0
  11. isa_model/core/services/intelligent_model_selector.py +547 -0
  12. isa_model/core/types.py +291 -0
  13. isa_model/deployment/__init__.py +2 -0
  14. isa_model/deployment/cloud/__init__.py +9 -0
  15. isa_model/deployment/cloud/modal/__init__.py +10 -0
  16. isa_model/deployment/cloud/modal/isa_vision_doc_service.py +766 -0
  17. isa_model/deployment/cloud/modal/isa_vision_table_service.py +532 -0
  18. isa_model/deployment/cloud/modal/isa_vision_ui_service.py +406 -0
  19. isa_model/deployment/cloud/modal/register_models.py +321 -0
  20. isa_model/deployment/runtime/deployed_service.py +338 -0
  21. isa_model/deployment/services/__init__.py +9 -0
  22. isa_model/deployment/services/auto_deploy_vision_service.py +537 -0
  23. isa_model/deployment/services/model_service.py +332 -0
  24. isa_model/deployment/services/service_monitor.py +356 -0
  25. isa_model/deployment/services/service_registry.py +527 -0
  26. isa_model/eval/__init__.py +80 -44
  27. isa_model/eval/config/__init__.py +10 -0
  28. isa_model/eval/config/evaluation_config.py +108 -0
  29. isa_model/eval/evaluators/__init__.py +18 -0
  30. isa_model/eval/evaluators/base_evaluator.py +503 -0
  31. isa_model/eval/evaluators/llm_evaluator.py +472 -0
  32. isa_model/eval/factory.py +417 -709
  33. isa_model/eval/infrastructure/__init__.py +24 -0
  34. isa_model/eval/infrastructure/experiment_tracker.py +466 -0
  35. isa_model/eval/metrics.py +191 -21
  36. isa_model/inference/ai_factory.py +187 -387
  37. isa_model/inference/providers/modal_provider.py +109 -0
  38. isa_model/inference/providers/yyds_provider.py +108 -0
  39. isa_model/inference/services/__init__.py +2 -1
  40. isa_model/inference/services/audio/base_stt_service.py +65 -1
  41. isa_model/inference/services/audio/base_tts_service.py +75 -1
  42. isa_model/inference/services/audio/openai_stt_service.py +189 -151
  43. isa_model/inference/services/audio/openai_tts_service.py +12 -10
  44. isa_model/inference/services/audio/replicate_tts_service.py +61 -56
  45. isa_model/inference/services/base_service.py +55 -55
  46. isa_model/inference/services/embedding/base_embed_service.py +65 -1
  47. isa_model/inference/services/embedding/ollama_embed_service.py +103 -43
  48. isa_model/inference/services/embedding/openai_embed_service.py +8 -10
  49. isa_model/inference/services/helpers/stacked_config.py +148 -0
  50. isa_model/inference/services/img/__init__.py +18 -0
  51. isa_model/inference/services/{vision → img}/base_image_gen_service.py +80 -35
  52. isa_model/inference/services/img/flux_professional_service.py +603 -0
  53. isa_model/inference/services/img/helpers/base_stacked_service.py +274 -0
  54. isa_model/inference/services/{vision → img}/replicate_image_gen_service.py +210 -69
  55. isa_model/inference/services/llm/__init__.py +3 -3
  56. isa_model/inference/services/llm/base_llm_service.py +519 -35
  57. isa_model/inference/services/llm/{llm_adapter.py → helpers/llm_adapter.py} +40 -0
  58. isa_model/inference/services/llm/helpers/llm_prompts.py +258 -0
  59. isa_model/inference/services/llm/helpers/llm_utils.py +280 -0
  60. isa_model/inference/services/llm/ollama_llm_service.py +150 -15
  61. isa_model/inference/services/llm/openai_llm_service.py +134 -31
  62. isa_model/inference/services/llm/yyds_llm_service.py +255 -0
  63. isa_model/inference/services/vision/__init__.py +38 -4
  64. isa_model/inference/services/vision/base_vision_service.py +241 -96
  65. isa_model/inference/services/vision/disabled/isA_vision_service.py +500 -0
  66. isa_model/inference/services/vision/doc_analysis_service.py +640 -0
  67. isa_model/inference/services/vision/helpers/base_stacked_service.py +274 -0
  68. isa_model/inference/services/vision/helpers/image_utils.py +272 -3
  69. isa_model/inference/services/vision/helpers/vision_prompts.py +297 -0
  70. isa_model/inference/services/vision/openai_vision_service.py +109 -170
  71. isa_model/inference/services/vision/replicate_vision_service.py +508 -0
  72. isa_model/inference/services/vision/ui_analysis_service.py +823 -0
  73. isa_model/scripts/register_models.py +370 -0
  74. isa_model/scripts/register_models_with_embeddings.py +510 -0
  75. isa_model/serving/__init__.py +19 -0
  76. isa_model/serving/api/__init__.py +10 -0
  77. isa_model/serving/api/fastapi_server.py +89 -0
  78. isa_model/serving/api/middleware/__init__.py +9 -0
  79. isa_model/serving/api/middleware/request_logger.py +88 -0
  80. isa_model/serving/api/routes/__init__.py +5 -0
  81. isa_model/serving/api/routes/health.py +82 -0
  82. isa_model/serving/api/routes/llm.py +19 -0
  83. isa_model/serving/api/routes/ui_analysis.py +223 -0
  84. isa_model/serving/api/routes/unified.py +202 -0
  85. isa_model/serving/api/routes/vision.py +19 -0
  86. isa_model/serving/api/schemas/__init__.py +17 -0
  87. isa_model/serving/api/schemas/common.py +33 -0
  88. isa_model/serving/api/schemas/ui_analysis.py +78 -0
  89. {isa_model-0.3.4.dist-info → isa_model-0.3.6.dist-info}/METADATA +4 -1
  90. isa_model-0.3.6.dist-info/RECORD +147 -0
  91. isa_model/core/model_manager.py +0 -208
  92. isa_model/core/model_registry.py +0 -342
  93. isa_model/inference/billing_tracker.py +0 -406
  94. isa_model/inference/services/llm/triton_llm_service.py +0 -481
  95. isa_model/inference/services/vision/ollama_vision_service.py +0 -194
  96. isa_model-0.3.4.dist-info/RECORD +0 -91
  97. /isa_model/core/{model_storage.py → models/model_storage.py} +0 -0
  98. /isa_model/inference/services/{vision → embedding}/helpers/text_splitter.py +0 -0
  99. {isa_model-0.3.4.dist-info → isa_model-0.3.6.dist-info}/WHEEL +0 -0
  100. {isa_model-0.3.4.dist-info → isa_model-0.3.6.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,426 @@
1
+ """
2
+ Centralized Configuration Management for ISA Model SDK
3
+
4
+ This module provides unified configuration management across all modules:
5
+ - Environment variable loading
6
+ - Provider API key management
7
+ - Global settings and defaults
8
+ - Configuration validation
9
+ """
10
+
11
+ import os
12
+ import logging
13
+ from typing import Dict, Any, Optional, List
14
+ from pathlib import Path
15
+ from dataclasses import dataclass, field
16
+ import yaml
17
+ import json
18
+ from dotenv import load_dotenv
19
+
20
+ from .types import Provider, DeploymentPlatform
21
+
22
+ logger = logging.getLogger(__name__)
23
+
24
+
25
+ @dataclass
26
+ class ProviderConfig:
27
+ """Configuration for a single provider"""
28
+ name: str
29
+ api_key: Optional[str] = None
30
+ api_base_url: Optional[str] = None
31
+ organization: Optional[str] = None
32
+ rate_limit_rpm: Optional[int] = None
33
+ rate_limit_tpm: Optional[int] = None
34
+ enabled: bool = True
35
+ metadata: Dict[str, Any] = field(default_factory=dict)
36
+
37
+
38
+ @dataclass
39
+ class DeploymentConfig:
40
+ """Configuration for deployment platforms"""
41
+ platform: DeploymentPlatform
42
+ endpoint: Optional[str] = None
43
+ api_key: Optional[str] = None
44
+ default_gpu: str = "T4"
45
+ default_memory_mb: int = 16384
46
+ auto_scaling: bool = True
47
+ scale_to_zero: bool = True
48
+ metadata: Dict[str, Any] = field(default_factory=dict)
49
+
50
+
51
+ @dataclass
52
+ class GlobalConfig:
53
+ """Global configuration settings"""
54
+ # Storage settings
55
+ default_storage_backend: str = "local"
56
+ storage_path: str = "./isa_model_data"
57
+ cache_dir: str = "./isa_model_cache"
58
+
59
+ # Database settings
60
+ use_supabase: bool = False
61
+ supabase_url: Optional[str] = None
62
+ supabase_key: Optional[str] = None
63
+ sqlite_path: str = "./isa_model.db"
64
+
65
+ # Billing settings
66
+ track_costs: bool = True
67
+ cost_alerts_enabled: bool = True
68
+ monthly_budget_usd: Optional[float] = None
69
+
70
+ # Health monitoring
71
+ health_check_interval: int = 300 # 5 minutes
72
+ health_check_timeout: int = 30 # 30 seconds
73
+
74
+ # Logging
75
+ log_level: str = "INFO"
76
+ log_file: Optional[str] = None
77
+
78
+ # Model caching
79
+ enable_model_cache: bool = True
80
+ cache_size_gb: int = 50
81
+ cache_cleanup_interval: int = 3600 # 1 hour
82
+
83
+
84
+ class ConfigManager:
85
+ """
86
+ Centralized configuration manager for the entire ISA Model SDK.
87
+
88
+ Features:
89
+ - Loads configuration from .env files, YAML files, and environment variables
90
+ - Manages provider API keys and settings
91
+ - Handles deployment platform configurations
92
+ - Provides unified access to all settings
93
+
94
+ Example:
95
+ ```python
96
+ from isa_model.core.config import ConfigManager
97
+
98
+ config = ConfigManager()
99
+
100
+ # Get provider configuration
101
+ openai_config = config.get_provider_config(Provider.OPENAI)
102
+
103
+ # Get deployment configuration
104
+ modal_config = config.get_deployment_config(DeploymentPlatform.MODAL)
105
+
106
+ # Check if provider is enabled
107
+ if config.is_provider_enabled(Provider.OPENAI):
108
+ print("OpenAI is configured and enabled")
109
+ ```
110
+ """
111
+
112
+ _instance = None
113
+ _initialized = False
114
+
115
+ def __new__(cls):
116
+ if cls._instance is None:
117
+ cls._instance = super().__new__(cls)
118
+ return cls._instance
119
+
120
+ def __init__(self):
121
+ """Initialize configuration manager"""
122
+ if not self._initialized:
123
+ self.global_config = GlobalConfig()
124
+ self.provider_configs: Dict[str, ProviderConfig] = {}
125
+ self.deployment_configs: Dict[str, DeploymentConfig] = {}
126
+
127
+ self._load_configuration()
128
+ ConfigManager._initialized = True
129
+
130
+ def _load_configuration(self):
131
+ """Load configuration from various sources"""
132
+ # 1. Load environment variables
133
+ self._load_env_files()
134
+
135
+ # 2. Load from YAML config file if exists
136
+ self._load_yaml_config()
137
+
138
+ # 3. Load provider configurations
139
+ self._load_provider_configs()
140
+
141
+ # 4. Load deployment configurations
142
+ self._load_deployment_configs()
143
+
144
+ # 5. Validate configuration
145
+ self._validate_configuration()
146
+
147
+ logger.info("Configuration loaded successfully")
148
+
149
+ def _load_env_files(self):
150
+ """Load environment variables from .env files"""
151
+ # Load from project root
152
+ project_root = self._find_project_root()
153
+ env_files = [
154
+ project_root / ".env",
155
+ project_root / ".env.local",
156
+ Path.cwd() / ".env",
157
+ ]
158
+
159
+ for env_file in env_files:
160
+ if env_file.exists():
161
+ load_dotenv(env_file)
162
+ logger.debug(f"Loaded environment from {env_file}")
163
+
164
+ def _find_project_root(self) -> Path:
165
+ """Find the project root directory"""
166
+ current = Path(__file__).parent
167
+ while current != current.parent:
168
+ if (current / "pyproject.toml").exists() or (current / "setup.py").exists():
169
+ return current
170
+ current = current.parent
171
+ return Path.cwd()
172
+
173
+ def _load_yaml_config(self):
174
+ """Load configuration from YAML file"""
175
+ config_files = [
176
+ Path.cwd() / "isa_model_config.yaml",
177
+ Path.cwd() / "config.yaml",
178
+ self._find_project_root() / "isa_model_config.yaml",
179
+ ]
180
+
181
+ for config_file in config_files:
182
+ if config_file.exists():
183
+ try:
184
+ with open(config_file, 'r') as f:
185
+ yaml_config = yaml.safe_load(f)
186
+
187
+ self._apply_yaml_config(yaml_config)
188
+ logger.info(f"Loaded YAML configuration from {config_file}")
189
+ break
190
+ except Exception as e:
191
+ logger.warning(f"Failed to load YAML config from {config_file}: {e}")
192
+
193
+ def _apply_yaml_config(self, yaml_config: Dict[str, Any]):
194
+ """Apply YAML configuration to global settings"""
195
+ if "global" in yaml_config:
196
+ global_settings = yaml_config["global"]
197
+ for key, value in global_settings.items():
198
+ if hasattr(self.global_config, key):
199
+ setattr(self.global_config, key, value)
200
+
201
+ def _load_provider_configs(self):
202
+ """Load provider configurations from environment"""
203
+
204
+ # Define provider environment variable patterns
205
+ provider_env_mapping = {
206
+ Provider.OPENAI: {
207
+ "api_key": ["OPENAI_API_KEY"],
208
+ "organization": ["OPENAI_ORG_ID", "OPENAI_ORGANIZATION"],
209
+ "api_base_url": ["OPENAI_API_BASE", "OPENAI_BASE_URL"],
210
+ },
211
+ Provider.REPLICATE: {
212
+ "api_key": ["REPLICATE_API_TOKEN", "REPLICATE_API_KEY"],
213
+ },
214
+ Provider.ANTHROPIC: {
215
+ "api_key": ["ANTHROPIC_API_KEY"],
216
+ },
217
+ Provider.GOOGLE: {
218
+ "api_key": ["GOOGLE_API_KEY", "GEMINI_API_KEY"],
219
+ },
220
+ Provider.YYDS: {
221
+ "api_key": ["YYDS_API_KEY"],
222
+ "api_base_url": ["YYDS_API_BASE", "YYDS_BASE_URL"],
223
+ },
224
+ }
225
+
226
+ for provider, env_vars in provider_env_mapping.items():
227
+ config = ProviderConfig(name=provider.value)
228
+
229
+ # Load API key
230
+ for env_var in env_vars.get("api_key", []):
231
+ if os.getenv(env_var):
232
+ config.api_key = os.getenv(env_var)
233
+ break
234
+
235
+ # Load other settings
236
+ for setting, env_var_list in env_vars.items():
237
+ if setting == "api_key":
238
+ continue
239
+ for env_var in env_var_list:
240
+ if os.getenv(env_var):
241
+ setattr(config, setting, os.getenv(env_var))
242
+ break
243
+
244
+ # Check if provider is enabled
245
+ config.enabled = bool(config.api_key)
246
+
247
+ self.provider_configs[provider.value] = config
248
+
249
+ def _load_deployment_configs(self):
250
+ """Load deployment platform configurations"""
251
+
252
+ deployment_env_mapping = {
253
+ DeploymentPlatform.MODAL: {
254
+ "api_key": ["MODAL_TOKEN"],
255
+ "endpoint": ["MODAL_ENDPOINT"],
256
+ },
257
+ DeploymentPlatform.RUNPOD: {
258
+ "api_key": ["RUNPOD_API_KEY"],
259
+ "endpoint": ["RUNPOD_ENDPOINT"],
260
+ },
261
+ DeploymentPlatform.KUBERNETES: {
262
+ "endpoint": ["K8S_ENDPOINT", "KUBERNETES_ENDPOINT"],
263
+ "api_key": ["K8S_TOKEN", "KUBERNETES_TOKEN"],
264
+ },
265
+ }
266
+
267
+ for platform, env_vars in deployment_env_mapping.items():
268
+ config = DeploymentConfig(platform=platform)
269
+
270
+ # Load settings from environment
271
+ for setting, env_var_list in env_vars.items():
272
+ for env_var in env_var_list:
273
+ if os.getenv(env_var):
274
+ setattr(config, setting, os.getenv(env_var))
275
+ break
276
+
277
+ self.deployment_configs[platform.value] = config
278
+
279
+ def _validate_configuration(self):
280
+ """Validate loaded configuration"""
281
+ warnings = []
282
+
283
+ # Check if any providers are configured
284
+ enabled_providers = [p for p in self.provider_configs.values() if p.enabled]
285
+ if not enabled_providers:
286
+ warnings.append("No providers are configured with API keys")
287
+
288
+ # Check storage path accessibility
289
+ storage_path = Path(self.global_config.storage_path)
290
+ try:
291
+ storage_path.mkdir(parents=True, exist_ok=True)
292
+ except Exception as e:
293
+ warnings.append(f"Storage path not accessible: {e}")
294
+
295
+ # Check database configuration
296
+ if self.global_config.use_supabase:
297
+ if not self.global_config.supabase_url or not self.global_config.supabase_key:
298
+ warnings.append("Supabase is enabled but URL/key not configured")
299
+
300
+ for warning in warnings:
301
+ logger.warning(f"Configuration warning: {warning}")
302
+
303
+ # Public API methods
304
+
305
+ def get_provider_config(self, provider: Provider) -> Optional[ProviderConfig]:
306
+ """Get configuration for a specific provider"""
307
+ return self.provider_configs.get(provider.value)
308
+
309
+ def get_deployment_config(self, platform: DeploymentPlatform) -> Optional[DeploymentConfig]:
310
+ """Get configuration for a specific deployment platform"""
311
+ return self.deployment_configs.get(platform.value)
312
+
313
+ def is_provider_enabled(self, provider: Provider) -> bool:
314
+ """Check if a provider is enabled and configured"""
315
+ config = self.get_provider_config(provider)
316
+ return config is not None and config.enabled and config.api_key is not None
317
+
318
+ def get_enabled_providers(self) -> List[Provider]:
319
+ """Get list of all enabled providers"""
320
+ enabled = []
321
+ for provider_str, config in self.provider_configs.items():
322
+ if config.enabled:
323
+ try:
324
+ enabled.append(Provider(provider_str))
325
+ except ValueError:
326
+ continue
327
+ return enabled
328
+
329
+ def get_provider_api_key(self, provider: Provider) -> Optional[str]:
330
+ """Get API key for a specific provider"""
331
+ config = self.get_provider_config(provider)
332
+ return config.api_key if config else None
333
+
334
+ def get_global_config(self) -> GlobalConfig:
335
+ """Get global configuration"""
336
+ return self.global_config
337
+
338
+ def update_provider_config(self, provider: Provider, **kwargs):
339
+ """Update provider configuration"""
340
+ if provider.value not in self.provider_configs:
341
+ self.provider_configs[provider.value] = ProviderConfig(name=provider.value)
342
+
343
+ config = self.provider_configs[provider.value]
344
+ for key, value in kwargs.items():
345
+ if hasattr(config, key):
346
+ setattr(config, key, value)
347
+
348
+ def save_config(self, config_file: Optional[Path] = None):
349
+ """Save current configuration to YAML file"""
350
+ if config_file is None:
351
+ config_file = Path.cwd() / "isa_model_config.yaml"
352
+
353
+ config_data = {
354
+ "global": {
355
+ "default_storage_backend": self.global_config.default_storage_backend,
356
+ "storage_path": self.global_config.storage_path,
357
+ "cache_dir": self.global_config.cache_dir,
358
+ "use_supabase": self.global_config.use_supabase,
359
+ "track_costs": self.global_config.track_costs,
360
+ "health_check_interval": self.global_config.health_check_interval,
361
+ "log_level": self.global_config.log_level,
362
+ },
363
+ "providers": {},
364
+ "deployments": {}
365
+ }
366
+
367
+ # Add provider configs (without API keys for security)
368
+ for provider_name, config in self.provider_configs.items():
369
+ config_data["providers"][provider_name] = {
370
+ "enabled": config.enabled,
371
+ "rate_limit_rpm": config.rate_limit_rpm,
372
+ "rate_limit_tpm": config.rate_limit_tpm,
373
+ "metadata": config.metadata,
374
+ }
375
+
376
+ # Add deployment configs (without API keys)
377
+ for platform_name, config in self.deployment_configs.items():
378
+ config_data["deployments"][platform_name] = {
379
+ "default_gpu": config.default_gpu,
380
+ "default_memory_mb": config.default_memory_mb,
381
+ "auto_scaling": config.auto_scaling,
382
+ "scale_to_zero": config.scale_to_zero,
383
+ "metadata": config.metadata,
384
+ }
385
+
386
+ try:
387
+ with open(config_file, 'w') as f:
388
+ yaml.dump(config_data, f, default_flow_style=False)
389
+ logger.info(f"Configuration saved to {config_file}")
390
+ except Exception as e:
391
+ logger.error(f"Failed to save configuration: {e}")
392
+
393
+ def get_summary(self) -> Dict[str, Any]:
394
+ """Get configuration summary"""
395
+ enabled_providers = [p.name for p in self.provider_configs.values() if p.enabled]
396
+ configured_deployments = [p.platform.value for p in self.deployment_configs.values() if p.api_key]
397
+
398
+ return {
399
+ "enabled_providers": enabled_providers,
400
+ "configured_deployments": configured_deployments,
401
+ "storage_backend": self.global_config.default_storage_backend,
402
+ "database": "supabase" if self.global_config.use_supabase else "sqlite",
403
+ "cost_tracking": self.global_config.track_costs,
404
+ "model_caching": self.global_config.enable_model_cache,
405
+ }
406
+
407
+
408
+ # Global configuration instance
409
+ config_manager = ConfigManager()
410
+
411
+ # Convenience functions
412
+ def get_provider_config(provider: Provider) -> Optional[ProviderConfig]:
413
+ """Get provider configuration"""
414
+ return config_manager.get_provider_config(provider)
415
+
416
+ def get_deployment_config(platform: DeploymentPlatform) -> Optional[DeploymentConfig]:
417
+ """Get deployment platform configuration"""
418
+ return config_manager.get_deployment_config(platform)
419
+
420
+ def is_provider_enabled(provider: Provider) -> bool:
421
+ """Check if provider is enabled"""
422
+ return config_manager.is_provider_enabled(provider)
423
+
424
+ def get_api_key(provider: Provider) -> Optional[str]:
425
+ """Get API key for provider"""
426
+ return config_manager.get_provider_api_key(provider)