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
@@ -3,27 +3,27 @@
3
3
 
4
4
  """
5
5
  Simplified AI Factory for creating inference services
6
- Uses the new service architecture with proper base classes and centralized API key management
6
+ Uses the new unified service architecture with centralized managers
7
7
  """
8
8
 
9
- from typing import Dict, Type, Any, Optional, Tuple, List, TYPE_CHECKING, cast
9
+ from typing import Dict, Any, Optional, TYPE_CHECKING
10
10
  import logging
11
- from isa_model.inference.providers.base_provider import BaseProvider
12
11
  from isa_model.inference.services.base_service import BaseService
13
- from isa_model.inference.base import ModelType
14
- from isa_model.inference.services.vision.base_vision_service import BaseVisionService
15
- from isa_model.inference.services.vision.base_image_gen_service import BaseImageGenService
12
+ from isa_model.core.models.model_manager import ModelManager
13
+ from isa_model.core.config import ConfigManager
16
14
 
17
15
  if TYPE_CHECKING:
18
16
  from isa_model.inference.services.audio.base_stt_service import BaseSTTService
19
17
  from isa_model.inference.services.audio.base_tts_service import BaseTTSService
18
+ from isa_model.inference.services.vision.base_vision_service import BaseVisionService
19
+ from isa_model.inference.services.img.base_image_gen_service import BaseImageGenService
20
20
 
21
21
  logger = logging.getLogger(__name__)
22
22
 
23
23
  class AIFactory:
24
24
  """
25
- Simplified Factory for creating AI services with proper inheritance hierarchy
26
- API key management is handled by individual providers
25
+ Modernized AI Factory using centralized ModelManager and ConfigManager
26
+ Provides unified interface with only 6 core methods: get_llm, get_vision, get_img, get_stt, get_tts, get_embed
27
27
  """
28
28
 
29
29
  _instance = None
@@ -37,239 +37,134 @@ class AIFactory:
37
37
  def __init__(self):
38
38
  """Initialize the AI Factory."""
39
39
  if not self._is_initialized:
40
- self._providers: Dict[str, Type[BaseProvider]] = {}
41
- self._services: Dict[Tuple[str, ModelType], Type[BaseService]] = {}
40
+ # Use centralized managers
41
+ self.model_manager = ModelManager()
42
+ self.config_manager = ConfigManager()
42
43
  self._cached_services: Dict[str, BaseService] = {}
43
- self._initialize_services()
44
- AIFactory._is_initialized = True
45
-
46
- def _initialize_services(self):
47
- """Initialize available providers and services"""
48
- try:
49
- # Register Ollama services
50
- self._register_ollama_services()
51
-
52
- # Register OpenAI services
53
- self._register_openai_services()
54
-
55
- # Register Replicate services
56
- self._register_replicate_services()
57
-
58
- logger.info("AI Factory initialized with centralized provider API key management")
59
-
60
- except Exception as e:
61
- logger.error(f"Error initializing services: {e}")
62
- logger.warning("Some services may not be available")
63
-
64
- def _register_ollama_services(self):
65
- """Register Ollama provider and services"""
66
- try:
67
- from isa_model.inference.providers.ollama_provider import OllamaProvider
68
- from isa_model.inference.services.llm.ollama_llm_service import OllamaLLMService
69
- from isa_model.inference.services.embedding.ollama_embed_service import OllamaEmbedService
70
- from isa_model.inference.services.vision.ollama_vision_service import OllamaVisionService
71
-
72
- self.register_provider('ollama', OllamaProvider)
73
- self.register_service('ollama', ModelType.LLM, OllamaLLMService)
74
- self.register_service('ollama', ModelType.EMBEDDING, OllamaEmbedService)
75
- self.register_service('ollama', ModelType.VISION, OllamaVisionService)
76
-
77
- logger.info("Ollama services registered successfully")
78
-
79
- except ImportError as e:
80
- logger.warning(f"Ollama services not available: {e}")
81
-
82
- def _register_openai_services(self):
83
- """Register OpenAI provider and services"""
84
- try:
85
- from isa_model.inference.providers.openai_provider import OpenAIProvider
86
- from isa_model.inference.services.llm.openai_llm_service import OpenAILLMService
87
- from isa_model.inference.services.audio.openai_tts_service import OpenAITTSService
88
- from isa_model.inference.services.audio.openai_stt_service import OpenAISTTService
89
- from isa_model.inference.services.embedding.openai_embed_service import OpenAIEmbedService
90
- from isa_model.inference.services.vision.openai_vision_service import OpenAIVisionService
91
-
92
- self.register_provider('openai', OpenAIProvider)
93
- self.register_service('openai', ModelType.LLM, OpenAILLMService)
94
- self.register_service('openai', ModelType.AUDIO, OpenAITTSService)
95
- self.register_service('openai', ModelType.EMBEDDING, OpenAIEmbedService)
96
- self.register_service('openai', ModelType.VISION, OpenAIVisionService)
97
-
98
- logger.info("OpenAI services registered successfully")
99
-
100
- except ImportError as e:
101
- logger.warning(f"OpenAI services not available: {e}")
102
-
103
- def _register_replicate_services(self):
104
- """Register Replicate provider and services"""
105
- try:
106
- from isa_model.inference.providers.replicate_provider import ReplicateProvider
107
- from isa_model.inference.services.vision.replicate_image_gen_service import ReplicateImageGenService
108
- from isa_model.inference.services.audio.replicate_tts_service import ReplicateTTSService
109
-
110
- self.register_provider('replicate', ReplicateProvider)
111
- self.register_service('replicate', ModelType.VISION, ReplicateImageGenService)
112
- self.register_service('replicate', ModelType.AUDIO, ReplicateTTSService)
113
-
114
- logger.info("Replicate services registered successfully")
115
-
116
- except ImportError as e:
117
- logger.warning(f"Replicate services not available: {e}")
118
-
119
- def register_provider(self, name: str, provider_class: Type[BaseProvider]) -> None:
120
- """Register an AI provider"""
121
- self._providers[name] = provider_class
122
-
123
- def register_service(self, provider_name: str, model_type: ModelType,
124
- service_class: Type[BaseService]) -> None:
125
- """Register a service type with its provider"""
126
- self._services[(provider_name, model_type)] = service_class
127
-
128
- def create_service(self, provider_name: str, model_type: ModelType,
129
- model_name: str, config: Optional[Dict[str, Any]] = None) -> BaseService:
130
- """Create a service instance with provider-managed configuration"""
131
- try:
132
- cache_key = f"{provider_name}_{model_type}_{model_name}"
133
-
134
- if cache_key in self._cached_services:
135
- return self._cached_services[cache_key]
136
-
137
- # Get provider and service classes
138
- provider_class = self._providers.get(provider_name)
139
- service_class = self._services.get((provider_name, model_type))
140
-
141
- if not provider_class:
142
- raise ValueError(f"No provider registered for '{provider_name}'")
143
-
144
- if not service_class:
145
- raise ValueError(
146
- f"No service registered for provider '{provider_name}' and model type '{model_type}'"
147
- )
148
-
149
- # Create provider with user config (provider handles .env loading)
150
- provider = provider_class(config=config)
151
- service = service_class(provider=provider, model_name=model_name)
152
-
153
- self._cached_services[cache_key] = service
154
- return service
155
44
 
156
- except Exception as e:
157
- logger.error(f"Error creating service: {e}")
158
- raise
45
+ logger.info("AI Factory initialized with centralized ModelManager and ConfigManager")
46
+ AIFactory._is_initialized = True
159
47
 
160
- # Convenient methods for common services with updated defaults
161
- def get_llm_service(self, model_name: Optional[str] = None, provider: Optional[str] = None,
162
- config: Optional[Dict[str, Any]] = None) -> BaseService:
48
+ # Core service methods using centralized architecture
49
+ def get_llm(self, model_name: Optional[str] = None, provider: Optional[str] = None,
50
+ config: Optional[Dict[str, Any]] = None) -> BaseService:
163
51
  """
164
52
  Get a LLM service instance with automatic defaults
165
53
 
166
54
  Args:
167
- model_name: Name of the model to use (defaults: OpenAI="gpt-4.1-nano", Ollama="llama3.2:3b")
55
+ model_name: Name of the model to use (defaults: OpenAI="gpt-4.1-mini", Ollama="llama3.2:3b", YYDS="claude-sonnet-4-20250514")
168
56
  provider: Provider name (defaults to 'openai' for production, 'ollama' for dev)
169
- config: Optional configuration dictionary (auto-loads from .env if not provided)
170
- Can include: streaming=True/False, temperature, max_tokens, etc.
57
+ config: Optional configuration dictionary
171
58
 
172
59
  Returns:
173
60
  LLM service instance
174
61
  """
175
62
  # Set defaults based on provider
176
63
  if provider == "openai":
177
- final_model_name = model_name or "gpt-4.1-nano"
64
+ final_model_name = model_name or "gpt-4.1-mini"
178
65
  final_provider = provider
179
66
  elif provider == "ollama":
180
67
  final_model_name = model_name or "llama3.2:3b-instruct-fp16"
181
68
  final_provider = provider
69
+ elif provider == "yyds":
70
+ final_model_name = model_name or "claude-sonnet-4-20250514"
71
+ final_provider = provider
182
72
  else:
183
73
  # Default provider selection - OpenAI with cheapest model
184
74
  final_provider = provider or "openai"
185
75
  if final_provider == "openai":
186
- final_model_name = model_name or "gpt-4.1-nano"
187
- else:
76
+ final_model_name = model_name or "gpt-4.1-mini"
77
+ elif final_provider == "ollama":
188
78
  final_model_name = model_name or "llama3.2:3b-instruct-fp16"
79
+ else:
80
+ final_model_name = model_name or "gpt-4.1-mini"
189
81
 
190
- return self.create_service(final_provider, ModelType.LLM, final_model_name, config)
191
-
192
- def get_embedding_service(self, model_name: Optional[str] = None, provider: Optional[str] = None,
193
- config: Optional[Dict[str, Any]] = None) -> BaseService:
194
- """
195
- Get an embedding service instance with automatic defaults
196
-
197
- Args:
198
- model_name: Name of the model to use (defaults: OpenAI="text-embedding-3-small", Ollama="bge-m3")
199
- provider: Provider name (defaults to 'openai' for production, 'ollama' for dev)
200
- config: Optional configuration dictionary (auto-loads from .env if not provided)
201
-
202
- Returns:
203
- Embedding service instance
204
- """
205
- # Set defaults based on provider
206
- if provider == "openai":
207
- final_model_name = model_name or "text-embedding-3-small"
208
- final_provider = provider
209
- elif provider == "ollama":
210
- final_model_name = model_name or "bge-m3"
211
- final_provider = provider
212
- else:
213
- # Default provider selection
214
- final_provider = provider or "openai"
82
+ # Create service using new centralized approach
83
+ try:
215
84
  if final_provider == "openai":
216
- final_model_name = model_name or "text-embedding-3-small"
85
+ from isa_model.inference.services.llm.openai_llm_service import OpenAILLMService
86
+ return OpenAILLMService(provider_name=final_provider, model_name=final_model_name,
87
+ model_manager=self.model_manager, config_manager=self.config_manager)
88
+ elif final_provider == "ollama":
89
+ from isa_model.inference.services.llm.ollama_llm_service import OllamaLLMService
90
+ return OllamaLLMService(provider_name=final_provider, model_name=final_model_name,
91
+ model_manager=self.model_manager, config_manager=self.config_manager)
92
+ elif final_provider == "yyds":
93
+ from isa_model.inference.services.llm.yyds_llm_service import YydsLLMService
94
+ return YydsLLMService(provider_name=final_provider, model_name=final_model_name,
95
+ model_manager=self.model_manager, config_manager=self.config_manager)
217
96
  else:
218
- final_model_name = model_name or "bge-m3"
219
-
220
- return self.create_service(final_provider, ModelType.EMBEDDING, final_model_name, config)
97
+ raise ValueError(f"Unsupported LLM provider: {final_provider}")
98
+ except Exception as e:
99
+ logger.error(f"Failed to create LLM service: {e}")
100
+ raise
221
101
 
222
- def get_vision_service(self, model_name: Optional[str] = None, provider: Optional[str] = None,
223
- config: Optional[Dict[str, Any]] = None) -> BaseVisionService:
102
+ def get_vision(
103
+ self,
104
+ model_name: Optional[str] = None,
105
+ provider: Optional[str] = None,
106
+ config: Optional[Dict[str, Any]] = None
107
+ ) -> 'BaseVisionService':
224
108
  """
225
- Get a vision service instance with automatic defaults
109
+ Get vision service with automatic defaults
226
110
 
227
111
  Args:
228
- model_name: Name of the model to use (defaults: OpenAI="gpt-4.1-mini", Ollama="gemma3:4b")
229
- provider: Provider name (defaults to 'openai' for production, 'ollama' for dev)
230
- config: Optional configuration dictionary (auto-loads from .env if not provided)
112
+ model_name: Model name. Special names:
113
+ - "isa_vision_table": Table extraction service
114
+ - "isa_vision_ui": UI detection service
115
+ - "isa_vision_doc": Document analysis service
116
+ - Default: "gpt-4.1-mini"
117
+ provider: Provider name (auto-detected for ISA services)
118
+ config: Optional configuration override
231
119
 
232
120
  Returns:
233
121
  Vision service instance
234
122
  """
235
- # Set defaults based on provider
123
+ # Handle special ISA vision services
124
+ if model_name in ["isa_vision_table", "isa_vision_ui", "isa_vision_doc"]:
125
+ try:
126
+ from isa_model.inference.services.vision.auto_deploy_vision_service import AutoDeployVisionService
127
+ logger.info(f"Creating auto-deploy service wrapper for {model_name}")
128
+ return AutoDeployVisionService(model_name, config)
129
+ except Exception as e:
130
+ logger.error(f"Failed to create ISA vision service: {e}")
131
+ raise
132
+
133
+ # Set defaults for regular services
236
134
  if provider == "openai":
237
135
  final_model_name = model_name or "gpt-4.1-mini"
238
136
  final_provider = provider
239
137
  elif provider == "ollama":
240
138
  final_model_name = model_name or "llama3.2-vision:latest"
241
139
  final_provider = provider
140
+ elif provider == "replicate":
141
+ final_model_name = model_name or "meta/llama-2-70b-chat"
142
+ final_provider = provider
242
143
  else:
243
144
  # Default provider selection
244
145
  final_provider = provider or "openai"
245
146
  if final_provider == "openai":
246
147
  final_model_name = model_name or "gpt-4.1-mini"
247
- else:
148
+ elif final_provider == "ollama":
248
149
  final_model_name = model_name or "llama3.2-vision:latest"
150
+ else:
151
+ final_model_name = model_name or "gpt-4.1-mini"
249
152
 
250
- return cast(BaseVisionService, self.create_service(final_provider, ModelType.VISION, final_model_name, config))
251
-
252
- def get_image_generation_service(self, model_name: Optional[str] = None, provider: Optional[str] = None,
253
- config: Optional[Dict[str, Any]] = None) -> 'BaseImageGenService':
254
- """
255
- Get an image generation service instance with automatic defaults
256
-
257
- Args:
258
- model_name: Name of the model to use (defaults: "black-forest-labs/flux-schnell" for production)
259
- provider: Provider name (defaults to 'replicate')
260
- config: Optional configuration dictionary (auto-loads from .env if not provided)
261
-
262
- Returns:
263
- Image generation service instance
264
- """
265
- # Set defaults based on provider
266
- final_provider = provider or "replicate"
267
- if final_provider == "replicate":
268
- final_model_name = model_name or "black-forest-labs/flux-schnell"
269
- else:
270
- final_model_name = model_name or "black-forest-labs/flux-schnell"
271
-
272
- return cast('BaseImageGenService', self.create_service(final_provider, ModelType.VISION, final_model_name, config))
153
+ # Create service using new centralized approach
154
+ try:
155
+ if final_provider == "openai":
156
+ from isa_model.inference.services.vision.openai_vision_service import OpenAIVisionService
157
+ return OpenAIVisionService(provider_name=final_provider, model_name=final_model_name,
158
+ model_manager=self.model_manager, config_manager=self.config_manager)
159
+ elif final_provider == "replicate":
160
+ from isa_model.inference.services.vision.replicate_vision_service import ReplicateVisionService
161
+ return ReplicateVisionService(provider_name=final_provider, model_name=final_model_name,
162
+ model_manager=self.model_manager, config_manager=self.config_manager)
163
+ else:
164
+ raise ValueError(f"Unsupported vision provider: {final_provider}")
165
+ except Exception as e:
166
+ logger.error(f"Failed to create vision service: {e}")
167
+ raise
273
168
 
274
169
  def get_img(self, type: str = "t2i", model_name: Optional[str] = None, provider: Optional[str] = None,
275
170
  config: Optional[Dict[str, Any]] = None) -> 'BaseImageGenService':
@@ -310,111 +205,138 @@ class AIFactory:
310
205
  else:
311
206
  raise ValueError(f"Unknown image generation type: {type}. Use 't2i' or 'i2i'")
312
207
 
313
- return cast('BaseImageGenService', self.create_service(final_provider, ModelType.VISION, final_model_name, config))
314
-
315
- def get_audio_service(self, model_name: Optional[str] = None, provider: Optional[str] = None,
316
- config: Optional[Dict[str, Any]] = None) -> BaseService:
208
+ # Create service using new centralized architecture
209
+ try:
210
+ if final_provider == "replicate":
211
+ from isa_model.inference.services.img.replicate_image_gen_service import ReplicateImageGenService
212
+ return ReplicateImageGenService(provider_name=final_provider, model_name=final_model_name,
213
+ model_manager=self.model_manager, config_manager=self.config_manager)
214
+ else:
215
+ raise ValueError(f"Unsupported image generation provider: {final_provider}")
216
+ except Exception as e:
217
+ logger.error(f"Failed to create image generation service: {e}")
218
+ raise
219
+
220
+ def get_stt(self, model_name: Optional[str] = None, provider: Optional[str] = None,
221
+ config: Optional[Dict[str, Any]] = None) -> 'BaseSTTService':
317
222
  """
318
- Get an audio service instance (TTS) with automatic defaults
223
+ Get Speech-to-Text service with automatic defaults
319
224
 
320
225
  Args:
321
- model_name: Name of the model to use (defaults: OpenAI="tts-1")
226
+ model_name: Name of the model to use (defaults: "whisper-1")
322
227
  provider: Provider name (defaults to 'openai')
323
- config: Optional configuration dictionary (auto-loads from .env if not provided)
228
+ config: Optional configuration dictionary
324
229
 
325
230
  Returns:
326
- Audio service instance
231
+ STT service instance
327
232
  """
328
- # Set defaults based on provider
233
+ # Set defaults
329
234
  final_provider = provider or "openai"
330
- if final_provider == "openai":
331
- final_model_name = model_name or "tts-1"
332
- else:
333
- final_model_name = model_name or "tts-1"
235
+ final_model_name = model_name or "whisper-1"
334
236
 
335
- return self.create_service(final_provider, ModelType.AUDIO, final_model_name, config)
336
-
337
- def get_tts_service(self, model_name: Optional[str] = None, provider: Optional[str] = None,
338
- config: Optional[Dict[str, Any]] = None) -> 'BaseTTSService':
237
+ # Create service using new centralized approach
238
+ try:
239
+ if final_provider == "openai":
240
+ from isa_model.inference.services.audio.openai_stt_service import OpenAISTTService
241
+ return OpenAISTTService(provider_name=final_provider, model_name=final_model_name,
242
+ model_manager=self.model_manager, config_manager=self.config_manager)
243
+ else:
244
+ raise ValueError(f"Unsupported STT provider: {final_provider}")
245
+ except Exception as e:
246
+ logger.error(f"Failed to create STT service: {e}")
247
+ raise
248
+
249
+ def get_tts(self, model_name: Optional[str] = None, provider: Optional[str] = None,
250
+ config: Optional[Dict[str, Any]] = None) -> 'BaseTTSService':
339
251
  """
340
- Get a Text-to-Speech service instance with automatic defaults
252
+ Get Text-to-Speech service with automatic defaults
341
253
 
342
254
  Args:
343
255
  model_name: Name of the model to use (defaults: Replicate="kokoro-82m", OpenAI="tts-1")
344
256
  provider: Provider name (defaults to 'replicate' for production, 'openai' for dev)
345
- config: Optional configuration dictionary (auto-loads from .env if not provided)
257
+ config: Optional configuration dictionary
346
258
 
347
259
  Returns:
348
260
  TTS service instance
349
261
  """
350
262
  # Set defaults based on provider
351
263
  if provider == "replicate":
352
- model_name = model_name or "kokoro-82m"
264
+ final_model_name = model_name or "kokoro-82m"
265
+ final_provider = provider
353
266
  elif provider == "openai":
354
- model_name = model_name or "tts-1"
267
+ final_model_name = model_name or "tts-1"
268
+ final_provider = provider
355
269
  else:
356
270
  # Default provider selection
357
- provider = provider or "replicate"
358
- if provider == "replicate":
359
- model_name = model_name or "kokoro-82m"
271
+ final_provider = provider or "replicate"
272
+ if final_provider == "replicate":
273
+ final_model_name = model_name or "kokoro-82m"
360
274
  else:
361
- model_name = model_name or "tts-1"
275
+ final_model_name = model_name or "tts-1"
362
276
 
363
- # Ensure model_name is never None
364
- if model_name is None:
365
- model_name = "tts-1"
366
-
367
- if provider == "replicate":
368
- from isa_model.inference.services.audio.replicate_tts_service import ReplicateTTSService
369
- from isa_model.inference.providers.replicate_provider import ReplicateProvider
370
-
371
- # Use full model name for Replicate
372
- if model_name == "kokoro-82m":
373
- model_name = "jaaari/kokoro-82m:f559560eb822dc509045f3921a1921234918b91739db4bf3daab2169b71c7a13"
374
-
375
- provider_instance = ReplicateProvider(config=config)
376
- return ReplicateTTSService(provider=provider_instance, model_name=model_name)
377
- else:
378
- return cast('BaseTTSService', self.get_audio_service(model_name, provider, config))
277
+ # Create service using new centralized approach
278
+ try:
279
+ if final_provider == "replicate":
280
+ from isa_model.inference.services.audio.replicate_tts_service import ReplicateTTSService
281
+ # Use full model name for Replicate
282
+ if final_model_name == "kokoro-82m":
283
+ final_model_name = "jaaari/kokoro-82m:f559560eb822dc509045f3921a1921234918b91739db4bf3daab2169b71c7a13"
284
+ return ReplicateTTSService(provider_name=final_provider, model_name=final_model_name,
285
+ model_manager=self.model_manager, config_manager=self.config_manager)
286
+ elif final_provider == "openai":
287
+ from isa_model.inference.services.audio.openai_tts_service import OpenAITTSService
288
+ return OpenAITTSService(provider_name=final_provider, model_name=final_model_name,
289
+ model_manager=self.model_manager, config_manager=self.config_manager)
290
+ else:
291
+ raise ValueError(f"Unsupported TTS provider: {final_provider}")
292
+ except Exception as e:
293
+ logger.error(f"Failed to create TTS service: {e}")
294
+ raise
379
295
 
380
- def get_stt_service(self, model_name: Optional[str] = None, provider: Optional[str] = None,
381
- config: Optional[Dict[str, Any]] = None) -> 'BaseSTTService':
296
+ def get_embed(self, model_name: Optional[str] = None, provider: Optional[str] = None,
297
+ config: Optional[Dict[str, Any]] = None) -> BaseService:
382
298
  """
383
- Get a Speech-to-Text service instance with automatic defaults
299
+ Get embedding service with automatic defaults
384
300
 
385
301
  Args:
386
- model_name: Name of the model to use (defaults: "whisper-1")
387
- provider: Provider name (defaults to 'openai')
388
- config: Optional configuration dictionary (auto-loads from .env if not provided)
302
+ model_name: Name of the model to use (defaults: OpenAI="text-embedding-3-small", Ollama="bge-m3")
303
+ provider: Provider name (defaults to 'openai' for production)
304
+ config: Optional configuration dictionary
389
305
 
390
306
  Returns:
391
- STT service instance
307
+ Embedding service instance
392
308
  """
393
309
  # Set defaults based on provider
394
- provider = provider or "openai"
395
310
  if provider == "openai":
396
- model_name = model_name or "whisper-1"
397
-
398
- # Ensure model_name is never None
399
- if model_name is None:
400
- model_name = "whisper-1"
401
-
402
- from isa_model.inference.services.audio.openai_stt_service import OpenAISTTService
403
- from isa_model.inference.providers.openai_provider import OpenAIProvider
311
+ final_model_name = model_name or "text-embedding-3-small"
312
+ final_provider = provider
313
+ elif provider == "ollama":
314
+ final_model_name = model_name or "bge-m3"
315
+ final_provider = provider
316
+ else:
317
+ # Default provider selection
318
+ final_provider = provider or "openai"
319
+ if final_provider == "openai":
320
+ final_model_name = model_name or "text-embedding-3-small"
321
+ else:
322
+ final_model_name = model_name or "bge-m3"
404
323
 
405
- # Create provider and service directly with config
406
- provider_instance = OpenAIProvider(config=config)
407
- return OpenAISTTService(provider=provider_instance, model_name=model_name)
408
-
409
- def get_available_services(self) -> Dict[str, List[str]]:
410
- """Get information about available services"""
411
- services = {}
412
- for (provider, model_type), service_class in self._services.items():
413
- if provider not in services:
414
- services[provider] = []
415
- services[provider].append(f"{model_type.value}: {service_class.__name__}")
416
- return services
417
-
324
+ # Create service using new centralized approach
325
+ try:
326
+ if final_provider == "openai":
327
+ from isa_model.inference.services.embedding.openai_embed_service import OpenAIEmbedService
328
+ return OpenAIEmbedService(provider_name=final_provider, model_name=final_model_name,
329
+ model_manager=self.model_manager, config_manager=self.config_manager)
330
+ elif final_provider == "ollama":
331
+ from isa_model.inference.services.embedding.ollama_embed_service import OllamaEmbedService
332
+ return OllamaEmbedService(provider_name=final_provider, model_name=final_model_name,
333
+ model_manager=self.model_manager, config_manager=self.config_manager)
334
+ else:
335
+ raise ValueError(f"Unsupported embedding provider: {final_provider}")
336
+ except Exception as e:
337
+ logger.error(f"Failed to create embedding service: {e}")
338
+ raise
339
+
418
340
  def clear_cache(self):
419
341
  """Clear the service cache"""
420
342
  self._cached_services.clear()
@@ -425,126 +347,4 @@ class AIFactory:
425
347
  """Get the singleton instance"""
426
348
  if cls._instance is None:
427
349
  cls._instance = cls()
428
- return cls._instance
429
-
430
- # Alias method for cleaner API
431
- def get_llm(self, model_name: Optional[str] = None, provider: Optional[str] = None,
432
- config: Optional[Dict[str, Any]] = None) -> BaseService:
433
- """
434
- Alias for get_llm_service with cleaner naming
435
-
436
- Usage:
437
- llm = AIFactory().get_llm() # Uses gpt-4.1-nano by default
438
- llm = AIFactory().get_llm(model_name="llama3.2", provider="ollama")
439
- llm = AIFactory().get_llm(model_name="gpt-4.1-mini", provider="openai", config={"streaming": True})
440
- """
441
- return self.get_llm_service(model_name, provider, config)
442
-
443
- def get_embed(self, model_name: Optional[str] = None, provider: Optional[str] = None,
444
- config: Optional[Dict[str, Any]] = None) -> 'BaseEmbedService':
445
- """
446
- Get embedding service with automatic defaults
447
-
448
- Args:
449
- model_name: Name of the model to use (defaults: OpenAI="text-embedding-3-small", Ollama="bge-m3")
450
- provider: Provider name (defaults to 'openai' for production)
451
- config: Optional configuration dictionary (auto-loads from .env if not provided)
452
-
453
- Returns:
454
- Embedding service instance
455
-
456
- Usage:
457
- # Default (OpenAI text-embedding-3-small)
458
- embed = AIFactory().get_embed()
459
-
460
- # Custom model
461
- embed = AIFactory().get_embed(model_name="text-embedding-3-large", provider="openai")
462
-
463
- # Development (Ollama)
464
- embed = AIFactory().get_embed(provider="ollama")
465
- """
466
- return self.get_embedding_service(model_name, provider, config)
467
-
468
- def get_stt(self, model_name: Optional[str] = None, provider: Optional[str] = None,
469
- config: Optional[Dict[str, Any]] = None) -> 'BaseSTTService':
470
- """
471
- Get Speech-to-Text service with automatic defaults
472
-
473
- Args:
474
- model_name: Name of the model to use (defaults: "whisper-1")
475
- provider: Provider name (defaults to 'openai')
476
- config: Optional configuration dictionary (auto-loads from .env if not provided)
477
-
478
- Returns:
479
- STT service instance
480
-
481
- Usage:
482
- # Default (OpenAI whisper-1)
483
- stt = AIFactory().get_stt()
484
-
485
- # Custom configuration
486
- stt = AIFactory().get_stt(model_name="whisper-1", provider="openai")
487
- """
488
- return self.get_stt_service(model_name, provider, config)
489
-
490
- def get_tts(self, model_name: Optional[str] = None, provider: Optional[str] = None,
491
- config: Optional[Dict[str, Any]] = None) -> 'BaseTTSService':
492
- """
493
- Get Text-to-Speech service with automatic defaults
494
-
495
- Args:
496
- model_name: Name of the model to use (defaults: Replicate="kokoro-82m", OpenAI="tts-1")
497
- provider: Provider name (defaults to 'replicate' for production, 'openai' for dev)
498
- config: Optional configuration dictionary (auto-loads from .env if not provided)
499
-
500
- Returns:
501
- TTS service instance
502
-
503
- Usage:
504
- # Default (Replicate kokoro-82m)
505
- tts = AIFactory().get_tts()
506
-
507
- # Development (OpenAI tts-1)
508
- tts = AIFactory().get_tts(provider="openai")
509
-
510
- # Custom model
511
- tts = AIFactory().get_tts(model_name="tts-1-hd", provider="openai")
512
- """
513
- return self.get_tts_service(model_name, provider, config)
514
-
515
- def get_vision_model(self, model_name: str, provider: str,
516
- config: Optional[Dict[str, Any]] = None) -> BaseService:
517
- """Alias for get_vision_service and get_image_generation_service"""
518
- if provider == "replicate":
519
- return self.get_image_generation_service(model_name, provider, config)
520
- else:
521
- return self.get_vision_service(model_name, provider, config)
522
-
523
- def get_vision(
524
- self,
525
- model_name: Optional[str] = None,
526
- provider: Optional[str] = None,
527
- config: Optional[Dict[str, Any]] = None
528
- ) -> 'BaseVisionService':
529
- """
530
- Get vision service with automatic defaults
531
-
532
- Args:
533
- model_name: Model name (default: gpt-4.1-nano)
534
- provider: Provider name (default: openai)
535
- config: Optional configuration override
536
-
537
- Returns:
538
- Vision service instance
539
- """
540
- # Set defaults
541
- if provider is None:
542
- provider = "openai"
543
- if model_name is None:
544
- model_name = "gpt-4.1-nano"
545
-
546
- return self.get_vision_service(
547
- model_name=model_name,
548
- provider=provider,
549
- config=config
550
- )
350
+ return cls._instance