isa-model 0.4.0__py3-none-any.whl → 0.4.4__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.
- isa_model/client.py +466 -43
- isa_model/core/cache/redis_cache.py +12 -3
- isa_model/core/config/config_manager.py +230 -3
- isa_model/core/config.py +90 -0
- isa_model/core/database/direct_db_client.py +114 -0
- isa_model/core/database/migration_manager.py +563 -0
- isa_model/core/database/migrations.py +21 -1
- isa_model/core/database/supabase_client.py +154 -19
- isa_model/core/dependencies.py +316 -0
- isa_model/core/discovery/__init__.py +19 -0
- isa_model/core/discovery/consul_discovery.py +190 -0
- isa_model/core/logging/__init__.py +54 -0
- isa_model/core/logging/influx_logger.py +523 -0
- isa_model/core/logging/loki_logger.py +160 -0
- isa_model/core/models/__init__.py +27 -18
- isa_model/core/models/config_models.py +625 -0
- isa_model/core/models/deployment_billing_tracker.py +430 -0
- isa_model/core/models/model_manager.py +35 -80
- isa_model/core/models/model_metadata.py +690 -0
- isa_model/core/models/model_repo.py +174 -18
- isa_model/core/models/system_models.py +857 -0
- isa_model/core/repositories/__init__.py +9 -0
- isa_model/core/repositories/config_repository.py +912 -0
- isa_model/core/services/intelligent_model_selector.py +399 -21
- isa_model/core/types.py +1 -0
- isa_model/deployment/__init__.py +5 -48
- isa_model/deployment/core/__init__.py +2 -31
- isa_model/deployment/core/deployment_manager.py +1278 -370
- isa_model/deployment/modal/__init__.py +8 -0
- isa_model/deployment/modal/config.py +136 -0
- isa_model/deployment/{services/auto_hf_modal_deployer.py → modal/deployer.py} +1 -1
- isa_model/deployment/modal/services/__init__.py +3 -0
- isa_model/deployment/modal/services/audio/__init__.py +1 -0
- isa_model/deployment/modal/services/embedding/__init__.py +1 -0
- isa_model/deployment/modal/services/llm/__init__.py +1 -0
- isa_model/deployment/modal/services/llm/isa_llm_service.py +424 -0
- isa_model/deployment/modal/services/video/__init__.py +1 -0
- isa_model/deployment/modal/services/vision/__init__.py +1 -0
- isa_model/deployment/models/org-org-acme-corp-tenant-a-service-llm-20250825-225822/tenant-a-service_modal_service.py +48 -0
- isa_model/deployment/models/org-test-org-123-prefix-test-service-llm-20250825-225822/prefix-test-service_modal_service.py +48 -0
- isa_model/deployment/models/test-llm-service-llm-20250825-204442/test-llm-service_modal_service.py +48 -0
- isa_model/deployment/models/test-monitoring-gpt2-llm-20250825-212906/test-monitoring-gpt2_modal_service.py +48 -0
- isa_model/deployment/models/test-monitoring-gpt2-llm-20250825-213009/test-monitoring-gpt2_modal_service.py +48 -0
- isa_model/deployment/storage/__init__.py +5 -0
- isa_model/deployment/storage/deployment_repository.py +824 -0
- isa_model/deployment/triton/__init__.py +10 -0
- isa_model/deployment/triton/config.py +196 -0
- isa_model/deployment/triton/configs/__init__.py +1 -0
- isa_model/deployment/triton/provider.py +512 -0
- isa_model/deployment/triton/scripts/__init__.py +1 -0
- isa_model/deployment/triton/templates/__init__.py +1 -0
- isa_model/inference/__init__.py +47 -1
- isa_model/inference/ai_factory.py +137 -10
- isa_model/inference/legacy_services/__init__.py +21 -0
- isa_model/inference/legacy_services/model_evaluation.py +637 -0
- isa_model/inference/legacy_services/model_service.py +573 -0
- isa_model/inference/legacy_services/model_serving.py +717 -0
- isa_model/inference/legacy_services/model_training.py +561 -0
- isa_model/inference/models/__init__.py +21 -0
- isa_model/inference/models/inference_config.py +551 -0
- isa_model/inference/models/inference_record.py +675 -0
- isa_model/inference/models/performance_models.py +714 -0
- isa_model/inference/repositories/__init__.py +9 -0
- isa_model/inference/repositories/inference_repository.py +828 -0
- isa_model/inference/services/audio/base_stt_service.py +184 -11
- isa_model/inference/services/audio/openai_stt_service.py +22 -6
- isa_model/inference/services/embedding/ollama_embed_service.py +15 -3
- isa_model/inference/services/embedding/resilient_embed_service.py +285 -0
- isa_model/inference/services/llm/__init__.py +10 -2
- isa_model/inference/services/llm/base_llm_service.py +335 -24
- isa_model/inference/services/llm/cerebras_llm_service.py +628 -0
- isa_model/inference/services/llm/helpers/llm_adapter.py +9 -4
- isa_model/inference/services/llm/helpers/llm_prompts.py +342 -0
- isa_model/inference/services/llm/helpers/llm_utils.py +321 -23
- isa_model/inference/services/llm/huggingface_llm_service.py +581 -0
- isa_model/inference/services/llm/ollama_llm_service.py +9 -2
- isa_model/inference/services/llm/openai_llm_service.py +33 -16
- isa_model/inference/services/llm/yyds_llm_service.py +8 -2
- isa_model/inference/services/vision/__init__.py +22 -1
- isa_model/inference/services/vision/helpers/image_utils.py +8 -5
- isa_model/inference/services/vision/isa_vision_service.py +65 -4
- isa_model/inference/services/vision/openai_vision_service.py +19 -10
- isa_model/inference/services/vision/vgg16_vision_service.py +257 -0
- isa_model/serving/api/cache_manager.py +245 -0
- isa_model/serving/api/dependencies/__init__.py +1 -0
- isa_model/serving/api/dependencies/auth.py +194 -0
- isa_model/serving/api/dependencies/database.py +139 -0
- isa_model/serving/api/error_handlers.py +284 -0
- isa_model/serving/api/fastapi_server.py +172 -22
- isa_model/serving/api/middleware/auth.py +8 -2
- isa_model/serving/api/middleware/security.py +23 -33
- isa_model/serving/api/middleware/tenant_context.py +414 -0
- isa_model/serving/api/routes/analytics.py +4 -1
- isa_model/serving/api/routes/config.py +645 -0
- isa_model/serving/api/routes/deployment_billing.py +315 -0
- isa_model/serving/api/routes/deployments.py +138 -2
- isa_model/serving/api/routes/gpu_gateway.py +440 -0
- isa_model/serving/api/routes/health.py +32 -12
- isa_model/serving/api/routes/inference_monitoring.py +486 -0
- isa_model/serving/api/routes/local_deployments.py +448 -0
- isa_model/serving/api/routes/tenants.py +575 -0
- isa_model/serving/api/routes/unified.py +680 -18
- isa_model/serving/api/routes/webhooks.py +479 -0
- isa_model/serving/api/startup.py +68 -54
- isa_model/utils/gpu_utils.py +311 -0
- {isa_model-0.4.0.dist-info → isa_model-0.4.4.dist-info}/METADATA +71 -24
- isa_model-0.4.4.dist-info/RECORD +180 -0
- isa_model/core/security/secrets.py +0 -358
- isa_model/core/storage/hf_storage.py +0 -419
- isa_model/core/storage/minio_storage.py +0 -0
- isa_model/deployment/cloud/__init__.py +0 -9
- isa_model/deployment/cloud/modal/__init__.py +0 -10
- isa_model/deployment/core/deployment_config.py +0 -356
- isa_model/deployment/core/isa_deployment_service.py +0 -401
- isa_model/deployment/gpu_int8_ds8/app/server.py +0 -66
- isa_model/deployment/gpu_int8_ds8/scripts/test_client.py +0 -43
- isa_model/deployment/gpu_int8_ds8/scripts/test_client_os.py +0 -35
- isa_model/deployment/runtime/deployed_service.py +0 -338
- isa_model/deployment/services/__init__.py +0 -9
- isa_model/deployment/services/auto_deploy_vision_service.py +0 -538
- isa_model/deployment/services/model_service.py +0 -332
- isa_model/deployment/services/service_monitor.py +0 -356
- isa_model/deployment/services/service_registry.py +0 -527
- isa_model/eval/__init__.py +0 -92
- isa_model/eval/benchmarks/__init__.py +0 -27
- isa_model/eval/benchmarks/multimodal_datasets.py +0 -460
- isa_model/eval/benchmarks.py +0 -701
- isa_model/eval/config/__init__.py +0 -10
- isa_model/eval/config/evaluation_config.py +0 -108
- isa_model/eval/evaluators/__init__.py +0 -24
- isa_model/eval/evaluators/audio_evaluator.py +0 -727
- isa_model/eval/evaluators/base_evaluator.py +0 -503
- isa_model/eval/evaluators/embedding_evaluator.py +0 -742
- isa_model/eval/evaluators/llm_evaluator.py +0 -472
- isa_model/eval/evaluators/vision_evaluator.py +0 -564
- isa_model/eval/example_evaluation.py +0 -395
- isa_model/eval/factory.py +0 -798
- isa_model/eval/infrastructure/__init__.py +0 -24
- isa_model/eval/infrastructure/experiment_tracker.py +0 -466
- isa_model/eval/isa_benchmarks.py +0 -700
- isa_model/eval/isa_integration.py +0 -582
- isa_model/eval/metrics.py +0 -951
- isa_model/eval/tests/unit/test_basic.py +0 -396
- isa_model/serving/api/routes/evaluations.py +0 -579
- isa_model/training/__init__.py +0 -168
- isa_model/training/annotation/annotation_schema.py +0 -47
- isa_model/training/annotation/processors/annotation_processor.py +0 -126
- isa_model/training/annotation/storage/dataset_manager.py +0 -131
- isa_model/training/annotation/storage/dataset_schema.py +0 -44
- isa_model/training/annotation/tests/test_annotation_flow.py +0 -109
- isa_model/training/annotation/tests/test_minio copy.py +0 -113
- isa_model/training/annotation/tests/test_minio_upload.py +0 -43
- isa_model/training/annotation/views/annotation_controller.py +0 -158
- isa_model/training/cloud/__init__.py +0 -22
- isa_model/training/cloud/job_orchestrator.py +0 -402
- isa_model/training/cloud/runpod_trainer.py +0 -454
- isa_model/training/cloud/storage_manager.py +0 -482
- isa_model/training/core/__init__.py +0 -26
- isa_model/training/core/config.py +0 -181
- isa_model/training/core/dataset.py +0 -222
- isa_model/training/core/trainer.py +0 -720
- isa_model/training/core/utils.py +0 -213
- isa_model/training/examples/intelligent_training_example.py +0 -281
- isa_model/training/factory.py +0 -424
- isa_model/training/intelligent/__init__.py +0 -25
- isa_model/training/intelligent/decision_engine.py +0 -643
- isa_model/training/intelligent/intelligent_factory.py +0 -888
- isa_model/training/intelligent/knowledge_base.py +0 -751
- isa_model/training/intelligent/resource_optimizer.py +0 -839
- isa_model/training/intelligent/task_classifier.py +0 -576
- isa_model/training/storage/__init__.py +0 -24
- isa_model/training/storage/core_integration.py +0 -439
- isa_model/training/storage/training_repository.py +0 -552
- isa_model/training/storage/training_storage.py +0 -628
- isa_model-0.4.0.dist-info/RECORD +0 -182
- /isa_model/deployment/{cloud/modal → modal/services/audio}/isa_audio_chatTTS_service.py +0 -0
- /isa_model/deployment/{cloud/modal → modal/services/audio}/isa_audio_fish_service.py +0 -0
- /isa_model/deployment/{cloud/modal → modal/services/audio}/isa_audio_openvoice_service.py +0 -0
- /isa_model/deployment/{cloud/modal → modal/services/audio}/isa_audio_service_v2.py +0 -0
- /isa_model/deployment/{cloud/modal → modal/services/embedding}/isa_embed_rerank_service.py +0 -0
- /isa_model/deployment/{cloud/modal → modal/services/video}/isa_video_hunyuan_service.py +0 -0
- /isa_model/deployment/{cloud/modal → modal/services/vision}/isa_vision_ocr_service.py +0 -0
- /isa_model/deployment/{cloud/modal → modal/services/vision}/isa_vision_qwen25_service.py +0 -0
- /isa_model/deployment/{cloud/modal → modal/services/vision}/isa_vision_table_service.py +0 -0
- /isa_model/deployment/{cloud/modal → modal/services/vision}/isa_vision_ui_service.py +0 -0
- /isa_model/deployment/{cloud/modal → modal/services/vision}/isa_vision_ui_service_optimized.py +0 -0
- /isa_model/deployment/{services → modal/services/vision}/simple_auto_deploy_vision_service.py +0 -0
- {isa_model-0.4.0.dist-info → isa_model-0.4.4.dist-info}/WHEEL +0 -0
- {isa_model-0.4.0.dist-info → isa_model-0.4.4.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
|
-
}
|