isa-model 0.3.91__py3-none-any.whl → 0.4.3__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 (228) hide show
  1. isa_model/client.py +1166 -584
  2. isa_model/core/cache/redis_cache.py +410 -0
  3. isa_model/core/config/config_manager.py +282 -12
  4. isa_model/core/config.py +91 -1
  5. isa_model/core/database/__init__.py +1 -0
  6. isa_model/core/database/direct_db_client.py +114 -0
  7. isa_model/core/database/migration_manager.py +563 -0
  8. isa_model/core/database/migrations.py +297 -0
  9. isa_model/core/database/supabase_client.py +258 -0
  10. isa_model/core/dependencies.py +316 -0
  11. isa_model/core/discovery/__init__.py +19 -0
  12. isa_model/core/discovery/consul_discovery.py +190 -0
  13. isa_model/core/logging/__init__.py +54 -0
  14. isa_model/core/logging/influx_logger.py +523 -0
  15. isa_model/core/logging/loki_logger.py +160 -0
  16. isa_model/core/models/__init__.py +46 -0
  17. isa_model/core/models/config_models.py +625 -0
  18. isa_model/core/models/deployment_billing_tracker.py +430 -0
  19. isa_model/core/models/model_billing_tracker.py +60 -88
  20. isa_model/core/models/model_manager.py +66 -25
  21. isa_model/core/models/model_metadata.py +690 -0
  22. isa_model/core/models/model_repo.py +217 -55
  23. isa_model/core/models/model_statistics_tracker.py +234 -0
  24. isa_model/core/models/model_storage.py +0 -1
  25. isa_model/core/models/model_version_manager.py +959 -0
  26. isa_model/core/models/system_models.py +857 -0
  27. isa_model/core/pricing_manager.py +2 -249
  28. isa_model/core/repositories/__init__.py +9 -0
  29. isa_model/core/repositories/config_repository.py +912 -0
  30. isa_model/core/resilience/circuit_breaker.py +366 -0
  31. isa_model/core/security/secrets.py +358 -0
  32. isa_model/core/services/__init__.py +2 -4
  33. isa_model/core/services/intelligent_model_selector.py +479 -370
  34. isa_model/core/storage/hf_storage.py +2 -2
  35. isa_model/core/types.py +8 -0
  36. isa_model/deployment/__init__.py +5 -48
  37. isa_model/deployment/core/__init__.py +2 -31
  38. isa_model/deployment/core/deployment_manager.py +1278 -368
  39. isa_model/deployment/local/__init__.py +31 -0
  40. isa_model/deployment/local/config.py +248 -0
  41. isa_model/deployment/local/gpu_gateway.py +607 -0
  42. isa_model/deployment/local/health_checker.py +428 -0
  43. isa_model/deployment/local/provider.py +586 -0
  44. isa_model/deployment/local/tensorrt_service.py +621 -0
  45. isa_model/deployment/local/transformers_service.py +644 -0
  46. isa_model/deployment/local/vllm_service.py +527 -0
  47. isa_model/deployment/modal/__init__.py +8 -0
  48. isa_model/deployment/modal/config.py +136 -0
  49. isa_model/deployment/modal/deployer.py +894 -0
  50. isa_model/deployment/modal/services/__init__.py +3 -0
  51. isa_model/deployment/modal/services/audio/__init__.py +1 -0
  52. isa_model/deployment/modal/services/audio/isa_audio_chatTTS_service.py +520 -0
  53. isa_model/deployment/modal/services/audio/isa_audio_openvoice_service.py +758 -0
  54. isa_model/deployment/modal/services/audio/isa_audio_service_v2.py +1044 -0
  55. isa_model/deployment/modal/services/embedding/__init__.py +1 -0
  56. isa_model/deployment/modal/services/embedding/isa_embed_rerank_service.py +296 -0
  57. isa_model/deployment/modal/services/llm/__init__.py +1 -0
  58. isa_model/deployment/modal/services/llm/isa_llm_service.py +424 -0
  59. isa_model/deployment/modal/services/video/__init__.py +1 -0
  60. isa_model/deployment/modal/services/video/isa_video_hunyuan_service.py +423 -0
  61. isa_model/deployment/modal/services/vision/__init__.py +1 -0
  62. isa_model/deployment/modal/services/vision/isa_vision_ocr_service.py +519 -0
  63. isa_model/deployment/modal/services/vision/isa_vision_qwen25_service.py +709 -0
  64. isa_model/deployment/modal/services/vision/isa_vision_table_service.py +676 -0
  65. isa_model/deployment/modal/services/vision/isa_vision_ui_service.py +833 -0
  66. isa_model/deployment/modal/services/vision/isa_vision_ui_service_optimized.py +660 -0
  67. isa_model/deployment/models/org-org-acme-corp-tenant-a-service-llm-20250825-225822/tenant-a-service_modal_service.py +48 -0
  68. isa_model/deployment/models/org-test-org-123-prefix-test-service-llm-20250825-225822/prefix-test-service_modal_service.py +48 -0
  69. isa_model/deployment/models/test-llm-service-llm-20250825-204442/test-llm-service_modal_service.py +48 -0
  70. isa_model/deployment/models/test-monitoring-gpt2-llm-20250825-212906/test-monitoring-gpt2_modal_service.py +48 -0
  71. isa_model/deployment/models/test-monitoring-gpt2-llm-20250825-213009/test-monitoring-gpt2_modal_service.py +48 -0
  72. isa_model/deployment/storage/__init__.py +5 -0
  73. isa_model/deployment/storage/deployment_repository.py +824 -0
  74. isa_model/deployment/triton/__init__.py +10 -0
  75. isa_model/deployment/triton/config.py +196 -0
  76. isa_model/deployment/triton/configs/__init__.py +1 -0
  77. isa_model/deployment/triton/provider.py +512 -0
  78. isa_model/deployment/triton/scripts/__init__.py +1 -0
  79. isa_model/deployment/triton/templates/__init__.py +1 -0
  80. isa_model/inference/__init__.py +47 -1
  81. isa_model/inference/ai_factory.py +179 -16
  82. isa_model/inference/legacy_services/__init__.py +21 -0
  83. isa_model/inference/legacy_services/model_evaluation.py +637 -0
  84. isa_model/inference/legacy_services/model_service.py +573 -0
  85. isa_model/inference/legacy_services/model_serving.py +717 -0
  86. isa_model/inference/legacy_services/model_training.py +561 -0
  87. isa_model/inference/models/__init__.py +21 -0
  88. isa_model/inference/models/inference_config.py +551 -0
  89. isa_model/inference/models/inference_record.py +675 -0
  90. isa_model/inference/models/performance_models.py +714 -0
  91. isa_model/inference/repositories/__init__.py +9 -0
  92. isa_model/inference/repositories/inference_repository.py +828 -0
  93. isa_model/inference/services/audio/__init__.py +21 -0
  94. isa_model/inference/services/audio/base_realtime_service.py +225 -0
  95. isa_model/inference/services/audio/base_stt_service.py +184 -11
  96. isa_model/inference/services/audio/isa_tts_service.py +0 -0
  97. isa_model/inference/services/audio/openai_realtime_service.py +320 -124
  98. isa_model/inference/services/audio/openai_stt_service.py +53 -11
  99. isa_model/inference/services/base_service.py +17 -1
  100. isa_model/inference/services/custom_model_manager.py +277 -0
  101. isa_model/inference/services/embedding/__init__.py +13 -0
  102. isa_model/inference/services/embedding/base_embed_service.py +111 -8
  103. isa_model/inference/services/embedding/isa_embed_service.py +305 -0
  104. isa_model/inference/services/embedding/ollama_embed_service.py +15 -3
  105. isa_model/inference/services/embedding/openai_embed_service.py +2 -4
  106. isa_model/inference/services/embedding/resilient_embed_service.py +285 -0
  107. isa_model/inference/services/embedding/tests/test_embedding.py +222 -0
  108. isa_model/inference/services/img/__init__.py +2 -2
  109. isa_model/inference/services/img/base_image_gen_service.py +24 -7
  110. isa_model/inference/services/img/replicate_image_gen_service.py +84 -422
  111. isa_model/inference/services/img/services/replicate_face_swap.py +193 -0
  112. isa_model/inference/services/img/services/replicate_flux.py +226 -0
  113. isa_model/inference/services/img/services/replicate_flux_kontext.py +219 -0
  114. isa_model/inference/services/img/services/replicate_sticker_maker.py +249 -0
  115. isa_model/inference/services/img/tests/test_img_client.py +297 -0
  116. isa_model/inference/services/llm/__init__.py +10 -2
  117. isa_model/inference/services/llm/base_llm_service.py +361 -26
  118. isa_model/inference/services/llm/cerebras_llm_service.py +628 -0
  119. isa_model/inference/services/llm/helpers/llm_adapter.py +71 -12
  120. isa_model/inference/services/llm/helpers/llm_prompts.py +342 -0
  121. isa_model/inference/services/llm/helpers/llm_utils.py +321 -23
  122. isa_model/inference/services/llm/huggingface_llm_service.py +581 -0
  123. isa_model/inference/services/llm/local_llm_service.py +747 -0
  124. isa_model/inference/services/llm/ollama_llm_service.py +11 -3
  125. isa_model/inference/services/llm/openai_llm_service.py +670 -56
  126. isa_model/inference/services/llm/yyds_llm_service.py +10 -3
  127. isa_model/inference/services/vision/__init__.py +27 -6
  128. isa_model/inference/services/vision/base_vision_service.py +118 -185
  129. isa_model/inference/services/vision/blip_vision_service.py +359 -0
  130. isa_model/inference/services/vision/helpers/image_utils.py +19 -10
  131. isa_model/inference/services/vision/isa_vision_service.py +634 -0
  132. isa_model/inference/services/vision/openai_vision_service.py +19 -10
  133. isa_model/inference/services/vision/tests/test_ocr_client.py +284 -0
  134. isa_model/inference/services/vision/vgg16_vision_service.py +257 -0
  135. isa_model/serving/api/cache_manager.py +245 -0
  136. isa_model/serving/api/dependencies/__init__.py +1 -0
  137. isa_model/serving/api/dependencies/auth.py +194 -0
  138. isa_model/serving/api/dependencies/database.py +139 -0
  139. isa_model/serving/api/error_handlers.py +284 -0
  140. isa_model/serving/api/fastapi_server.py +240 -18
  141. isa_model/serving/api/middleware/auth.py +317 -0
  142. isa_model/serving/api/middleware/security.py +268 -0
  143. isa_model/serving/api/middleware/tenant_context.py +414 -0
  144. isa_model/serving/api/routes/analytics.py +489 -0
  145. isa_model/serving/api/routes/config.py +645 -0
  146. isa_model/serving/api/routes/deployment_billing.py +315 -0
  147. isa_model/serving/api/routes/deployments.py +475 -0
  148. isa_model/serving/api/routes/gpu_gateway.py +440 -0
  149. isa_model/serving/api/routes/health.py +32 -12
  150. isa_model/serving/api/routes/inference_monitoring.py +486 -0
  151. isa_model/serving/api/routes/local_deployments.py +448 -0
  152. isa_model/serving/api/routes/logs.py +430 -0
  153. isa_model/serving/api/routes/settings.py +582 -0
  154. isa_model/serving/api/routes/tenants.py +575 -0
  155. isa_model/serving/api/routes/unified.py +992 -171
  156. isa_model/serving/api/routes/webhooks.py +479 -0
  157. isa_model/serving/api/startup.py +318 -0
  158. isa_model/serving/modal_proxy_server.py +249 -0
  159. isa_model/utils/gpu_utils.py +311 -0
  160. {isa_model-0.3.91.dist-info → isa_model-0.4.3.dist-info}/METADATA +76 -22
  161. isa_model-0.4.3.dist-info/RECORD +193 -0
  162. isa_model/deployment/cloud/__init__.py +0 -9
  163. isa_model/deployment/cloud/modal/__init__.py +0 -10
  164. isa_model/deployment/cloud/modal/isa_vision_doc_service.py +0 -766
  165. isa_model/deployment/cloud/modal/isa_vision_table_service.py +0 -532
  166. isa_model/deployment/cloud/modal/isa_vision_ui_service.py +0 -406
  167. isa_model/deployment/cloud/modal/register_models.py +0 -321
  168. isa_model/deployment/core/deployment_config.py +0 -356
  169. isa_model/deployment/core/isa_deployment_service.py +0 -401
  170. isa_model/deployment/gpu_int8_ds8/app/server.py +0 -66
  171. isa_model/deployment/gpu_int8_ds8/scripts/test_client.py +0 -43
  172. isa_model/deployment/gpu_int8_ds8/scripts/test_client_os.py +0 -35
  173. isa_model/deployment/runtime/deployed_service.py +0 -338
  174. isa_model/deployment/services/__init__.py +0 -9
  175. isa_model/deployment/services/auto_deploy_vision_service.py +0 -538
  176. isa_model/deployment/services/model_service.py +0 -332
  177. isa_model/deployment/services/service_monitor.py +0 -356
  178. isa_model/deployment/services/service_registry.py +0 -527
  179. isa_model/eval/__init__.py +0 -92
  180. isa_model/eval/benchmarks.py +0 -469
  181. isa_model/eval/config/__init__.py +0 -10
  182. isa_model/eval/config/evaluation_config.py +0 -108
  183. isa_model/eval/evaluators/__init__.py +0 -18
  184. isa_model/eval/evaluators/base_evaluator.py +0 -503
  185. isa_model/eval/evaluators/llm_evaluator.py +0 -472
  186. isa_model/eval/factory.py +0 -531
  187. isa_model/eval/infrastructure/__init__.py +0 -24
  188. isa_model/eval/infrastructure/experiment_tracker.py +0 -466
  189. isa_model/eval/metrics.py +0 -798
  190. isa_model/inference/adapter/unified_api.py +0 -248
  191. isa_model/inference/services/helpers/stacked_config.py +0 -148
  192. isa_model/inference/services/img/flux_professional_service.py +0 -603
  193. isa_model/inference/services/img/helpers/base_stacked_service.py +0 -274
  194. isa_model/inference/services/others/table_transformer_service.py +0 -61
  195. isa_model/inference/services/vision/doc_analysis_service.py +0 -640
  196. isa_model/inference/services/vision/helpers/base_stacked_service.py +0 -274
  197. isa_model/inference/services/vision/ui_analysis_service.py +0 -823
  198. isa_model/scripts/inference_tracker.py +0 -283
  199. isa_model/scripts/mlflow_manager.py +0 -379
  200. isa_model/scripts/model_registry.py +0 -465
  201. isa_model/scripts/register_models.py +0 -370
  202. isa_model/scripts/register_models_with_embeddings.py +0 -510
  203. isa_model/scripts/start_mlflow.py +0 -95
  204. isa_model/scripts/training_tracker.py +0 -257
  205. isa_model/training/__init__.py +0 -74
  206. isa_model/training/annotation/annotation_schema.py +0 -47
  207. isa_model/training/annotation/processors/annotation_processor.py +0 -126
  208. isa_model/training/annotation/storage/dataset_manager.py +0 -131
  209. isa_model/training/annotation/storage/dataset_schema.py +0 -44
  210. isa_model/training/annotation/tests/test_annotation_flow.py +0 -109
  211. isa_model/training/annotation/tests/test_minio copy.py +0 -113
  212. isa_model/training/annotation/tests/test_minio_upload.py +0 -43
  213. isa_model/training/annotation/views/annotation_controller.py +0 -158
  214. isa_model/training/cloud/__init__.py +0 -22
  215. isa_model/training/cloud/job_orchestrator.py +0 -402
  216. isa_model/training/cloud/runpod_trainer.py +0 -454
  217. isa_model/training/cloud/storage_manager.py +0 -482
  218. isa_model/training/core/__init__.py +0 -23
  219. isa_model/training/core/config.py +0 -181
  220. isa_model/training/core/dataset.py +0 -222
  221. isa_model/training/core/trainer.py +0 -720
  222. isa_model/training/core/utils.py +0 -213
  223. isa_model/training/factory.py +0 -424
  224. isa_model-0.3.91.dist-info/RECORD +0 -138
  225. /isa_model/{core/storage/minio_storage.py → deployment/modal/services/audio/isa_audio_fish_service.py} +0 -0
  226. /isa_model/deployment/{services → modal/services/vision}/simple_auto_deploy_vision_service.py +0 -0
  227. {isa_model-0.3.91.dist-info → isa_model-0.4.3.dist-info}/WHEEL +0 -0
  228. {isa_model-0.3.91.dist-info → isa_model-0.4.3.dist-info}/top_level.txt +0 -0
@@ -1,538 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Auto-Deploy Vision Service Wrapper
4
-
5
- Automatically deploys Modal services when needed and shuts them down after completion.
6
- """
7
-
8
- import logging
9
- from typing import Dict, Any, Optional, Union, List, BinaryIO
10
-
11
- from isa_model.inference.services.vision.base_vision_service import BaseVisionService
12
-
13
- logger = logging.getLogger(__name__)
14
-
15
-
16
- class AutoDeployVisionService(BaseVisionService):
17
- """
18
- Vision service wrapper that handles automatic deployment and shutdown
19
- of Modal services for ISA vision tasks.
20
- """
21
-
22
- def __init__(self, model_name: str = "isa_vision_table", config: dict = None, **kwargs):
23
- # Initialize BaseVisionService with modal provider
24
- super().__init__("modal", model_name, **kwargs)
25
- self.model_name = model_name
26
- self.config = config or {}
27
- self.underlying_service = None
28
- self._factory = None
29
-
30
- def _get_factory(self):
31
- """Get AIFactory instance for service management"""
32
- if not self._factory:
33
- from isa_model.inference.ai_factory import AIFactory
34
- self._factory = AIFactory()
35
- return self._factory
36
-
37
- def _ensure_service_deployed(self) -> bool:
38
- """Ensure the Modal service is deployed before use"""
39
- factory = self._get_factory()
40
-
41
- # Check if service is available
42
- app_name = factory._get_modal_app_name(self.model_name)
43
- if not factory._check_modal_service_availability(app_name):
44
- logger.info(f"Deploying {self.model_name} service...")
45
- success = factory._auto_deploy_modal_service(self.model_name)
46
- if not success:
47
- logger.error(f"Failed to deploy {self.model_name}")
48
- return False
49
-
50
- # Wait for service to be ready
51
- logger.info(f"Waiting for {self.model_name} service to be ready...")
52
- self._wait_for_service_ready(app_name)
53
-
54
- # Initialize underlying service using proper factory method
55
- if not self.underlying_service:
56
- # Use the factory's get_vision method with modal provider
57
- self.underlying_service = factory.get_vision(
58
- model_name=self.model_name,
59
- provider_name="modal"
60
- )
61
-
62
- return True
63
-
64
- def _wait_for_service_ready(self, app_name: str, max_wait_time: int = 300):
65
- """Wait for Modal service to be ready by checking health endpoint"""
66
- import time
67
-
68
- logger.info(f"Waiting up to {max_wait_time} seconds for {app_name} to be ready...")
69
- start_time = time.time()
70
-
71
- while time.time() - start_time < max_wait_time:
72
- try:
73
- import modal
74
- # Try to lookup the app and call health check
75
- app = modal.App.lookup(app_name)
76
-
77
- # Different health check methods for different services
78
- if "table" in app_name:
79
- service_cls = modal.Cls.from_name(app_name, "QwenTableExtractionService")
80
- elif "ui" in app_name:
81
- service_cls = modal.Cls.from_name(app_name, "UIDetectionService")
82
- elif "doc" in app_name:
83
- service_cls = modal.Cls.from_name(app_name, "DocumentAnalysisService")
84
- else:
85
- # Default wait time for unknown services
86
- time.sleep(60)
87
- return
88
-
89
- # Try to call health check
90
- health_result = service_cls().health_check.remote()
91
- if health_result and health_result.get("status") == "healthy":
92
- logger.info(f"Service {app_name} is ready!")
93
- return
94
-
95
- except Exception as e:
96
- logger.debug(f"Service not ready yet: {e}")
97
-
98
- # Wait 10 seconds before next check
99
- time.sleep(10)
100
- logger.info(f"Still waiting for {app_name}... ({int(time.time() - start_time)}s elapsed)")
101
-
102
- logger.warning(f"Service {app_name} may not be fully ready after {max_wait_time}s")
103
-
104
- def _shutdown_service_after_completion(self):
105
- """Shutdown Modal service after task completion"""
106
- try:
107
- factory = self._get_factory()
108
- factory._shutdown_modal_service(self.model_name)
109
- except Exception as e:
110
- logger.warning(f"Failed to shutdown service {self.model_name}: {e}")
111
-
112
- async def extract_table_data(
113
- self,
114
- image: Union[str, BinaryIO],
115
- extraction_format: str = "markdown",
116
- custom_prompt: Optional[str] = None
117
- ) -> Dict[str, Any]:
118
- """Extract table data with auto-deploy and shutdown"""
119
-
120
- # Ensure service is deployed
121
- if not self._ensure_service_deployed():
122
- return {
123
- 'success': False,
124
- 'error': f'Failed to deploy {self.model_name} service',
125
- 'service': self.model_name
126
- }
127
-
128
- try:
129
- # Call the underlying service
130
- result = await self.underlying_service.extract_table_data(
131
- image=image,
132
- extraction_format=extraction_format,
133
- custom_prompt=custom_prompt
134
- )
135
-
136
- # Shutdown service after completion
137
- self._shutdown_service_after_completion()
138
-
139
- return result
140
-
141
- except Exception as e:
142
- logger.error(f"Table extraction failed: {e}")
143
- # Still try to shutdown even if request failed
144
- self._shutdown_service_after_completion()
145
-
146
- return {
147
- 'success': False,
148
- 'error': str(e),
149
- 'service': self.model_name
150
- }
151
-
152
- async def batch_extract_tables(
153
- self,
154
- images: List[Union[str, BinaryIO]],
155
- extraction_format: str = "markdown"
156
- ) -> Dict[str, Any]:
157
- """Batch extract tables with auto-deploy and shutdown"""
158
-
159
- # Ensure service is deployed
160
- if not self._ensure_service_deployed():
161
- return {
162
- 'success': False,
163
- 'error': f'Failed to deploy {self.model_name} service',
164
- 'service': self.model_name
165
- }
166
-
167
- try:
168
- # Call the underlying service
169
- result = await self.underlying_service.batch_extract_tables(
170
- images=images,
171
- extraction_format=extraction_format
172
- )
173
-
174
- # Shutdown service after completion
175
- self._shutdown_service_after_completion()
176
-
177
- return result
178
-
179
- except Exception as e:
180
- logger.error(f"Batch table extraction failed: {e}")
181
- # Still try to shutdown even if request failed
182
- self._shutdown_service_after_completion()
183
-
184
- return {
185
- 'success': False,
186
- 'error': str(e),
187
- 'service': self.model_name
188
- }
189
-
190
- async def detect_ui_elements(self, image: Union[str, BinaryIO]) -> Dict[str, Any]:
191
- """Detect UI elements with auto-deploy and shutdown"""
192
-
193
- # Ensure service is deployed
194
- if not self._ensure_service_deployed():
195
- return {
196
- 'success': False,
197
- 'error': f'Failed to deploy {self.model_name} service',
198
- 'service': self.model_name
199
- }
200
-
201
- try:
202
- # Call the underlying service
203
- result = await self.underlying_service.detect_ui_elements(image=image)
204
-
205
- # Shutdown service after completion
206
- self._shutdown_service_after_completion()
207
-
208
- return result
209
-
210
- except Exception as e:
211
- logger.error(f"UI detection failed: {e}")
212
- # Still try to shutdown even if request failed
213
- self._shutdown_service_after_completion()
214
-
215
- return {
216
- 'success': False,
217
- 'error': str(e),
218
- 'service': self.model_name
219
- }
220
-
221
- async def analyze_document(self, image: Union[str, BinaryIO]) -> Dict[str, Any]:
222
- """Analyze document with auto-deploy and shutdown"""
223
-
224
- # Ensure service is deployed
225
- if not self._ensure_service_deployed():
226
- return {
227
- 'success': False,
228
- 'error': f'Failed to deploy {self.model_name} service',
229
- 'service': self.model_name
230
- }
231
-
232
- try:
233
- # Call the underlying service
234
- result = await self.underlying_service.analyze_document(image=image)
235
-
236
- # Shutdown service after completion
237
- self._shutdown_service_after_completion()
238
-
239
- return result
240
-
241
- except Exception as e:
242
- logger.error(f"Document analysis failed: {e}")
243
- # Still try to shutdown even if request failed
244
- self._shutdown_service_after_completion()
245
-
246
- return {
247
- 'success': False,
248
- 'error': str(e),
249
- 'service': self.model_name
250
- }
251
-
252
- # Implement all required abstract methods from BaseVisionService
253
-
254
- async def invoke(
255
- self,
256
- image: Union[str, BinaryIO],
257
- prompt: Optional[str] = None,
258
- task: Optional[str] = None,
259
- **kwargs
260
- ) -> Dict[str, Any]:
261
- """Unified invoke method for all vision operations"""
262
- if not self._ensure_service_deployed():
263
- return {
264
- 'success': False,
265
- 'error': f'Failed to deploy {self.model_name} service',
266
- 'service': self.model_name
267
- }
268
-
269
- try:
270
- result = await self.underlying_service.invoke(image=image, prompt=prompt, task=task, **kwargs)
271
- self._shutdown_service_after_completion()
272
- return result
273
- except Exception as e:
274
- logger.error(f"Vision invoke failed: {e}")
275
- self._shutdown_service_after_completion()
276
- return {
277
- 'success': False,
278
- 'error': str(e),
279
- 'service': self.model_name
280
- }
281
-
282
- async def analyze_image(
283
- self,
284
- image: Union[str, BinaryIO],
285
- prompt: Optional[str] = None,
286
- max_tokens: int = 1000
287
- ) -> Dict[str, Any]:
288
- """Analyze image with auto-deploy and shutdown"""
289
- if not self._ensure_service_deployed():
290
- return {
291
- 'success': False,
292
- 'error': f'Failed to deploy {self.model_name} service',
293
- 'service': self.model_name
294
- }
295
-
296
- try:
297
- result = await self.underlying_service.analyze_image(
298
- image=image, prompt=prompt, max_tokens=max_tokens
299
- )
300
- self._shutdown_service_after_completion()
301
- return result
302
- except Exception as e:
303
- logger.error(f"Image analysis failed: {e}")
304
- self._shutdown_service_after_completion()
305
- return {
306
- 'success': False,
307
- 'error': str(e),
308
- 'service': self.model_name
309
- }
310
-
311
- async def analyze_images(
312
- self,
313
- images: List[Union[str, BinaryIO]],
314
- prompt: Optional[str] = None,
315
- max_tokens: int = 1000
316
- ) -> List[Dict[str, Any]]:
317
- """Analyze multiple images with auto-deploy and shutdown"""
318
- if not self._ensure_service_deployed():
319
- return [{
320
- 'success': False,
321
- 'error': f'Failed to deploy {self.model_name} service',
322
- 'service': self.model_name
323
- }]
324
-
325
- try:
326
- result = await self.underlying_service.analyze_images(
327
- images=images, prompt=prompt, max_tokens=max_tokens
328
- )
329
- self._shutdown_service_after_completion()
330
- return result
331
- except Exception as e:
332
- logger.error(f"Multiple image analysis failed: {e}")
333
- self._shutdown_service_after_completion()
334
- return [{
335
- 'success': False,
336
- 'error': str(e),
337
- 'service': self.model_name
338
- }]
339
-
340
- async def describe_image(
341
- self,
342
- image: Union[str, BinaryIO],
343
- detail_level: str = "medium"
344
- ) -> Dict[str, Any]:
345
- """Generate detailed description of image"""
346
- if not self._ensure_service_deployed():
347
- return {
348
- 'success': False,
349
- 'error': f'Failed to deploy {self.model_name} service',
350
- 'service': self.model_name
351
- }
352
-
353
- try:
354
- result = await self.underlying_service.describe_image(
355
- image=image, detail_level=detail_level
356
- )
357
- self._shutdown_service_after_completion()
358
- return result
359
- except Exception as e:
360
- logger.error(f"Image description failed: {e}")
361
- self._shutdown_service_after_completion()
362
- return {
363
- 'success': False,
364
- 'error': str(e),
365
- 'service': self.model_name
366
- }
367
-
368
- async def extract_text(self, image: Union[str, BinaryIO]) -> Dict[str, Any]:
369
- """Extract text from image (OCR)"""
370
- if not self._ensure_service_deployed():
371
- return {
372
- 'success': False,
373
- 'error': f'Failed to deploy {self.model_name} service',
374
- 'service': self.model_name
375
- }
376
-
377
- try:
378
- result = await self.underlying_service.extract_text(image=image)
379
- self._shutdown_service_after_completion()
380
- return result
381
- except Exception as e:
382
- logger.error(f"Text extraction failed: {e}")
383
- self._shutdown_service_after_completion()
384
- return {
385
- 'success': False,
386
- 'error': str(e),
387
- 'service': self.model_name
388
- }
389
-
390
- async def detect_objects(
391
- self,
392
- image: Union[str, BinaryIO],
393
- confidence_threshold: float = 0.5
394
- ) -> Dict[str, Any]:
395
- """Detect objects in image"""
396
- if not self._ensure_service_deployed():
397
- return {
398
- 'success': False,
399
- 'error': f'Failed to deploy {self.model_name} service',
400
- 'service': self.model_name
401
- }
402
-
403
- try:
404
- result = await self.underlying_service.detect_objects(
405
- image=image, confidence_threshold=confidence_threshold
406
- )
407
- self._shutdown_service_after_completion()
408
- return result
409
- except Exception as e:
410
- logger.error(f"Object detection failed: {e}")
411
- self._shutdown_service_after_completion()
412
- return {
413
- 'success': False,
414
- 'error': str(e),
415
- 'service': self.model_name
416
- }
417
-
418
- async def get_object_coordinates(
419
- self,
420
- image: Union[str, BinaryIO],
421
- object_name: str
422
- ) -> Dict[str, Any]:
423
- """Get coordinates of a specific object in the image"""
424
- if not self._ensure_service_deployed():
425
- return {
426
- 'success': False,
427
- 'error': f'Failed to deploy {self.model_name} service',
428
- 'service': self.model_name
429
- }
430
-
431
- try:
432
- result = await self.underlying_service.get_object_coordinates(
433
- image=image, object_name=object_name
434
- )
435
- self._shutdown_service_after_completion()
436
- return result
437
- except Exception as e:
438
- logger.error(f"Object coordinate detection failed: {e}")
439
- self._shutdown_service_after_completion()
440
- return {
441
- 'success': False,
442
- 'error': str(e),
443
- 'service': self.model_name
444
- }
445
-
446
- async def classify_image(
447
- self,
448
- image: Union[str, BinaryIO],
449
- categories: Optional[List[str]] = None
450
- ) -> Dict[str, Any]:
451
- """Classify image into categories"""
452
- if not self._ensure_service_deployed():
453
- return {
454
- 'success': False,
455
- 'error': f'Failed to deploy {self.model_name} service',
456
- 'service': self.model_name
457
- }
458
-
459
- try:
460
- result = await self.underlying_service.classify_image(
461
- image=image, categories=categories
462
- )
463
- self._shutdown_service_after_completion()
464
- return result
465
- except Exception as e:
466
- logger.error(f"Image classification failed: {e}")
467
- self._shutdown_service_after_completion()
468
- return {
469
- 'success': False,
470
- 'error': str(e),
471
- 'service': self.model_name
472
- }
473
-
474
- async def compare_images(
475
- self,
476
- image1: Union[str, BinaryIO],
477
- image2: Union[str, BinaryIO]
478
- ) -> Dict[str, Any]:
479
- """Compare two images for similarity"""
480
- if not self._ensure_service_deployed():
481
- return {
482
- 'success': False,
483
- 'error': f'Failed to deploy {self.model_name} service',
484
- 'service': self.model_name
485
- }
486
-
487
- try:
488
- result = await self.underlying_service.compare_images(
489
- image1=image1, image2=image2
490
- )
491
- self._shutdown_service_after_completion()
492
- return result
493
- except Exception as e:
494
- logger.error(f"Image comparison failed: {e}")
495
- self._shutdown_service_after_completion()
496
- return {
497
- 'success': False,
498
- 'error': str(e),
499
- 'service': self.model_name
500
- }
501
-
502
- def get_supported_formats(self) -> List[str]:
503
- """Get list of supported image formats"""
504
- # Initialize underlying service if needed (non-async)
505
- if not self.underlying_service:
506
- factory = self._get_factory()
507
- self.underlying_service = factory.get_vision(
508
- model_name=self.model_name,
509
- provider_name="modal"
510
- )
511
- return self.underlying_service.get_supported_formats()
512
-
513
- def get_max_image_size(self) -> Dict[str, int]:
514
- """Get maximum supported image dimensions"""
515
- # Initialize underlying service if needed (non-async)
516
- if not self.underlying_service:
517
- factory = self._get_factory()
518
- self.underlying_service = factory.get_vision(
519
- model_name=self.model_name,
520
- provider_name="modal"
521
- )
522
- return self.underlying_service.get_max_image_size()
523
-
524
- async def close(self):
525
- """Cleanup resources"""
526
- if self.underlying_service:
527
- await self.underlying_service.close()
528
- # Ensure service is shut down
529
- self._shutdown_service_after_completion()
530
-
531
- # Pass through other methods to underlying service
532
- async def generate_image(self, prompt: str, **kwargs) -> Dict[str, Any]:
533
- """Generate image (not applicable for ISA vision services)"""
534
- return {
535
- 'success': False,
536
- 'error': 'Image generation not supported by ISA vision services',
537
- 'service': self.model_name
538
- }