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.
- isa_model/client.py +1166 -584
- isa_model/core/cache/redis_cache.py +410 -0
- isa_model/core/config/config_manager.py +282 -12
- isa_model/core/config.py +91 -1
- isa_model/core/database/__init__.py +1 -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 +297 -0
- isa_model/core/database/supabase_client.py +258 -0
- 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 +46 -0
- isa_model/core/models/config_models.py +625 -0
- isa_model/core/models/deployment_billing_tracker.py +430 -0
- isa_model/core/models/model_billing_tracker.py +60 -88
- isa_model/core/models/model_manager.py +66 -25
- isa_model/core/models/model_metadata.py +690 -0
- isa_model/core/models/model_repo.py +217 -55
- isa_model/core/models/model_statistics_tracker.py +234 -0
- isa_model/core/models/model_storage.py +0 -1
- isa_model/core/models/model_version_manager.py +959 -0
- isa_model/core/models/system_models.py +857 -0
- isa_model/core/pricing_manager.py +2 -249
- isa_model/core/repositories/__init__.py +9 -0
- isa_model/core/repositories/config_repository.py +912 -0
- isa_model/core/resilience/circuit_breaker.py +366 -0
- isa_model/core/security/secrets.py +358 -0
- isa_model/core/services/__init__.py +2 -4
- isa_model/core/services/intelligent_model_selector.py +479 -370
- isa_model/core/storage/hf_storage.py +2 -2
- isa_model/core/types.py +8 -0
- isa_model/deployment/__init__.py +5 -48
- isa_model/deployment/core/__init__.py +2 -31
- isa_model/deployment/core/deployment_manager.py +1278 -368
- isa_model/deployment/local/__init__.py +31 -0
- isa_model/deployment/local/config.py +248 -0
- isa_model/deployment/local/gpu_gateway.py +607 -0
- isa_model/deployment/local/health_checker.py +428 -0
- isa_model/deployment/local/provider.py +586 -0
- isa_model/deployment/local/tensorrt_service.py +621 -0
- isa_model/deployment/local/transformers_service.py +644 -0
- isa_model/deployment/local/vllm_service.py +527 -0
- isa_model/deployment/modal/__init__.py +8 -0
- isa_model/deployment/modal/config.py +136 -0
- isa_model/deployment/modal/deployer.py +894 -0
- isa_model/deployment/modal/services/__init__.py +3 -0
- isa_model/deployment/modal/services/audio/__init__.py +1 -0
- isa_model/deployment/modal/services/audio/isa_audio_chatTTS_service.py +520 -0
- isa_model/deployment/modal/services/audio/isa_audio_openvoice_service.py +758 -0
- isa_model/deployment/modal/services/audio/isa_audio_service_v2.py +1044 -0
- isa_model/deployment/modal/services/embedding/__init__.py +1 -0
- isa_model/deployment/modal/services/embedding/isa_embed_rerank_service.py +296 -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/video/isa_video_hunyuan_service.py +423 -0
- isa_model/deployment/modal/services/vision/__init__.py +1 -0
- isa_model/deployment/modal/services/vision/isa_vision_ocr_service.py +519 -0
- isa_model/deployment/modal/services/vision/isa_vision_qwen25_service.py +709 -0
- isa_model/deployment/modal/services/vision/isa_vision_table_service.py +676 -0
- isa_model/deployment/modal/services/vision/isa_vision_ui_service.py +833 -0
- isa_model/deployment/modal/services/vision/isa_vision_ui_service_optimized.py +660 -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 +179 -16
- 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/__init__.py +21 -0
- isa_model/inference/services/audio/base_realtime_service.py +225 -0
- isa_model/inference/services/audio/base_stt_service.py +184 -11
- isa_model/inference/services/audio/isa_tts_service.py +0 -0
- isa_model/inference/services/audio/openai_realtime_service.py +320 -124
- isa_model/inference/services/audio/openai_stt_service.py +53 -11
- isa_model/inference/services/base_service.py +17 -1
- isa_model/inference/services/custom_model_manager.py +277 -0
- isa_model/inference/services/embedding/__init__.py +13 -0
- isa_model/inference/services/embedding/base_embed_service.py +111 -8
- isa_model/inference/services/embedding/isa_embed_service.py +305 -0
- isa_model/inference/services/embedding/ollama_embed_service.py +15 -3
- isa_model/inference/services/embedding/openai_embed_service.py +2 -4
- isa_model/inference/services/embedding/resilient_embed_service.py +285 -0
- isa_model/inference/services/embedding/tests/test_embedding.py +222 -0
- isa_model/inference/services/img/__init__.py +2 -2
- isa_model/inference/services/img/base_image_gen_service.py +24 -7
- isa_model/inference/services/img/replicate_image_gen_service.py +84 -422
- isa_model/inference/services/img/services/replicate_face_swap.py +193 -0
- isa_model/inference/services/img/services/replicate_flux.py +226 -0
- isa_model/inference/services/img/services/replicate_flux_kontext.py +219 -0
- isa_model/inference/services/img/services/replicate_sticker_maker.py +249 -0
- isa_model/inference/services/img/tests/test_img_client.py +297 -0
- isa_model/inference/services/llm/__init__.py +10 -2
- isa_model/inference/services/llm/base_llm_service.py +361 -26
- isa_model/inference/services/llm/cerebras_llm_service.py +628 -0
- isa_model/inference/services/llm/helpers/llm_adapter.py +71 -12
- 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/local_llm_service.py +747 -0
- isa_model/inference/services/llm/ollama_llm_service.py +11 -3
- isa_model/inference/services/llm/openai_llm_service.py +670 -56
- isa_model/inference/services/llm/yyds_llm_service.py +10 -3
- isa_model/inference/services/vision/__init__.py +27 -6
- isa_model/inference/services/vision/base_vision_service.py +118 -185
- isa_model/inference/services/vision/blip_vision_service.py +359 -0
- isa_model/inference/services/vision/helpers/image_utils.py +19 -10
- isa_model/inference/services/vision/isa_vision_service.py +634 -0
- isa_model/inference/services/vision/openai_vision_service.py +19 -10
- isa_model/inference/services/vision/tests/test_ocr_client.py +284 -0
- 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 +240 -18
- isa_model/serving/api/middleware/auth.py +317 -0
- isa_model/serving/api/middleware/security.py +268 -0
- isa_model/serving/api/middleware/tenant_context.py +414 -0
- isa_model/serving/api/routes/analytics.py +489 -0
- 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 +475 -0
- 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/logs.py +430 -0
- isa_model/serving/api/routes/settings.py +582 -0
- isa_model/serving/api/routes/tenants.py +575 -0
- isa_model/serving/api/routes/unified.py +992 -171
- isa_model/serving/api/routes/webhooks.py +479 -0
- isa_model/serving/api/startup.py +318 -0
- isa_model/serving/modal_proxy_server.py +249 -0
- isa_model/utils/gpu_utils.py +311 -0
- {isa_model-0.3.91.dist-info → isa_model-0.4.3.dist-info}/METADATA +76 -22
- isa_model-0.4.3.dist-info/RECORD +193 -0
- isa_model/deployment/cloud/__init__.py +0 -9
- isa_model/deployment/cloud/modal/__init__.py +0 -10
- isa_model/deployment/cloud/modal/isa_vision_doc_service.py +0 -766
- isa_model/deployment/cloud/modal/isa_vision_table_service.py +0 -532
- isa_model/deployment/cloud/modal/isa_vision_ui_service.py +0 -406
- isa_model/deployment/cloud/modal/register_models.py +0 -321
- 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.py +0 -469
- isa_model/eval/config/__init__.py +0 -10
- isa_model/eval/config/evaluation_config.py +0 -108
- isa_model/eval/evaluators/__init__.py +0 -18
- isa_model/eval/evaluators/base_evaluator.py +0 -503
- isa_model/eval/evaluators/llm_evaluator.py +0 -472
- isa_model/eval/factory.py +0 -531
- isa_model/eval/infrastructure/__init__.py +0 -24
- isa_model/eval/infrastructure/experiment_tracker.py +0 -466
- isa_model/eval/metrics.py +0 -798
- isa_model/inference/adapter/unified_api.py +0 -248
- isa_model/inference/services/helpers/stacked_config.py +0 -148
- isa_model/inference/services/img/flux_professional_service.py +0 -603
- isa_model/inference/services/img/helpers/base_stacked_service.py +0 -274
- isa_model/inference/services/others/table_transformer_service.py +0 -61
- isa_model/inference/services/vision/doc_analysis_service.py +0 -640
- isa_model/inference/services/vision/helpers/base_stacked_service.py +0 -274
- isa_model/inference/services/vision/ui_analysis_service.py +0 -823
- isa_model/scripts/inference_tracker.py +0 -283
- isa_model/scripts/mlflow_manager.py +0 -379
- isa_model/scripts/model_registry.py +0 -465
- isa_model/scripts/register_models.py +0 -370
- isa_model/scripts/register_models_with_embeddings.py +0 -510
- isa_model/scripts/start_mlflow.py +0 -95
- isa_model/scripts/training_tracker.py +0 -257
- isa_model/training/__init__.py +0 -74
- 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 -23
- 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/factory.py +0 -424
- isa_model-0.3.91.dist-info/RECORD +0 -138
- /isa_model/{core/storage/minio_storage.py → deployment/modal/services/audio/isa_audio_fish_service.py} +0 -0
- /isa_model/deployment/{services → modal/services/vision}/simple_auto_deploy_vision_service.py +0 -0
- {isa_model-0.3.91.dist-info → isa_model-0.4.3.dist-info}/WHEEL +0 -0
- {isa_model-0.3.91.dist-info → isa_model-0.4.3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,359 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
BLIP Vision Service
|
4
|
+
Computer vision service using BLIP for image captioning and description
|
5
|
+
Based on the notebook implementation
|
6
|
+
"""
|
7
|
+
|
8
|
+
import os
|
9
|
+
import logging
|
10
|
+
from typing import Dict, List, Any, Optional, Union, BinaryIO
|
11
|
+
from PIL import Image
|
12
|
+
import io
|
13
|
+
|
14
|
+
from .base_vision_service import BaseVisionService
|
15
|
+
|
16
|
+
logger = logging.getLogger(__name__)
|
17
|
+
|
18
|
+
def _lazy_import_blip_deps():
|
19
|
+
"""Lazy import BLIP dependencies"""
|
20
|
+
try:
|
21
|
+
import torch
|
22
|
+
import tensorflow as tf
|
23
|
+
from transformers import BlipProcessor, BlipForConditionalGeneration
|
24
|
+
|
25
|
+
return {
|
26
|
+
'torch': torch,
|
27
|
+
'tf': tf,
|
28
|
+
'BlipProcessor': BlipProcessor,
|
29
|
+
'BlipForConditionalGeneration': BlipForConditionalGeneration,
|
30
|
+
'available': True
|
31
|
+
}
|
32
|
+
except ImportError as e:
|
33
|
+
logger.warning(f"BLIP dependencies not available: {e}")
|
34
|
+
return {'available': False}
|
35
|
+
|
36
|
+
class BLIPVisionService(BaseVisionService):
|
37
|
+
"""
|
38
|
+
BLIP-based vision service for image captioning and description
|
39
|
+
Provides an alternative implementation to VLM-based captioning
|
40
|
+
"""
|
41
|
+
|
42
|
+
def __init__(self, model_name: str = "Salesforce/blip-image-captioning-base"):
|
43
|
+
"""
|
44
|
+
Initialize BLIP vision service
|
45
|
+
|
46
|
+
Args:
|
47
|
+
model_name: Hugging Face model name for BLIP
|
48
|
+
"""
|
49
|
+
super().__init__()
|
50
|
+
|
51
|
+
self.model_name = model_name
|
52
|
+
self.processor = None
|
53
|
+
self.model = None
|
54
|
+
|
55
|
+
# Lazy load dependencies
|
56
|
+
self.blip_components = _lazy_import_blip_deps()
|
57
|
+
|
58
|
+
if not self.blip_components['available']:
|
59
|
+
raise ImportError("BLIP dependencies (transformers, torch) are required")
|
60
|
+
|
61
|
+
# Load BLIP model
|
62
|
+
self._load_blip_model()
|
63
|
+
|
64
|
+
def _load_blip_model(self):
|
65
|
+
"""Load BLIP model and processor"""
|
66
|
+
try:
|
67
|
+
# Load the pretrained BLIP processor and model
|
68
|
+
self.processor = self.blip_components['BlipProcessor'].from_pretrained(self.model_name)
|
69
|
+
self.model = self.blip_components['BlipForConditionalGeneration'].from_pretrained(self.model_name)
|
70
|
+
|
71
|
+
logger.info(f"BLIP model loaded: {self.model_name}")
|
72
|
+
|
73
|
+
except Exception as e:
|
74
|
+
logger.error(f"Error loading BLIP model: {e}")
|
75
|
+
raise
|
76
|
+
|
77
|
+
def _preprocess_image(self, image: Union[str, BinaryIO]) -> Image.Image:
|
78
|
+
"""
|
79
|
+
Preprocess image for BLIP input
|
80
|
+
|
81
|
+
Args:
|
82
|
+
image: Image path or binary data
|
83
|
+
|
84
|
+
Returns:
|
85
|
+
PIL Image in RGB format
|
86
|
+
"""
|
87
|
+
try:
|
88
|
+
# Handle different image input types
|
89
|
+
if isinstance(image, str):
|
90
|
+
# File path
|
91
|
+
pil_image = Image.open(image).convert('RGB')
|
92
|
+
elif hasattr(image, 'read'):
|
93
|
+
# Binary IO
|
94
|
+
image_data = image.read()
|
95
|
+
pil_image = Image.open(io.BytesIO(image_data)).convert('RGB')
|
96
|
+
else:
|
97
|
+
raise ValueError("Unsupported image format")
|
98
|
+
|
99
|
+
return pil_image
|
100
|
+
|
101
|
+
except Exception as e:
|
102
|
+
logger.error(f"Error preprocessing image: {e}")
|
103
|
+
raise
|
104
|
+
|
105
|
+
def _generate_text(self, image: Image.Image, prompt: str) -> str:
|
106
|
+
"""
|
107
|
+
Generate text for image using BLIP
|
108
|
+
|
109
|
+
Args:
|
110
|
+
image: PIL Image
|
111
|
+
prompt: Text prompt for generation
|
112
|
+
|
113
|
+
Returns:
|
114
|
+
Generated text
|
115
|
+
"""
|
116
|
+
try:
|
117
|
+
# Prepare inputs for BLIP model
|
118
|
+
inputs = self.processor(images=image, text=prompt, return_tensors="pt")
|
119
|
+
|
120
|
+
# Generate text output
|
121
|
+
output = self.model.generate(**inputs)
|
122
|
+
|
123
|
+
# Decode output
|
124
|
+
result = self.processor.decode(output[0], skip_special_tokens=True)
|
125
|
+
|
126
|
+
return result
|
127
|
+
|
128
|
+
except Exception as e:
|
129
|
+
logger.error(f"Error generating text: {e}")
|
130
|
+
raise
|
131
|
+
|
132
|
+
async def describe_image(self,
|
133
|
+
image: Union[str, BinaryIO],
|
134
|
+
detail_level: str = "medium") -> Dict[str, Any]:
|
135
|
+
"""
|
136
|
+
Generate description for image using BLIP
|
137
|
+
|
138
|
+
Args:
|
139
|
+
image: Image path or binary data
|
140
|
+
detail_level: Level of detail (not used in BLIP, maintained for compatibility)
|
141
|
+
|
142
|
+
Returns:
|
143
|
+
Description results
|
144
|
+
"""
|
145
|
+
try:
|
146
|
+
# Preprocess image
|
147
|
+
pil_image = self._preprocess_image(image)
|
148
|
+
|
149
|
+
# Generate caption using BLIP
|
150
|
+
prompt = "This is a picture of" # Following notebook implementation
|
151
|
+
caption = self._generate_text(pil_image, prompt)
|
152
|
+
|
153
|
+
return {
|
154
|
+
"task": "describe",
|
155
|
+
"service": "BLIPVisionService",
|
156
|
+
"description": caption,
|
157
|
+
"detail_level": detail_level,
|
158
|
+
"model_type": "BLIP",
|
159
|
+
"prompt_used": prompt,
|
160
|
+
"success": True
|
161
|
+
}
|
162
|
+
|
163
|
+
except Exception as e:
|
164
|
+
logger.error(f"Error describing image: {e}")
|
165
|
+
return {
|
166
|
+
"error": str(e),
|
167
|
+
"service": "BLIPVisionService",
|
168
|
+
"success": False
|
169
|
+
}
|
170
|
+
|
171
|
+
async def analyze_image(self,
|
172
|
+
image: Union[str, BinaryIO],
|
173
|
+
prompt: Optional[str] = None,
|
174
|
+
max_tokens: int = 1000) -> Dict[str, Any]:
|
175
|
+
"""
|
176
|
+
Analyze image using BLIP
|
177
|
+
|
178
|
+
Args:
|
179
|
+
image: Image path or binary data
|
180
|
+
prompt: Optional custom prompt
|
181
|
+
max_tokens: Not used for BLIP
|
182
|
+
|
183
|
+
Returns:
|
184
|
+
Analysis results
|
185
|
+
"""
|
186
|
+
try:
|
187
|
+
# Preprocess image
|
188
|
+
pil_image = self._preprocess_image(image)
|
189
|
+
|
190
|
+
# Use custom prompt or default
|
191
|
+
if prompt:
|
192
|
+
analysis_prompt = prompt
|
193
|
+
else:
|
194
|
+
analysis_prompt = "This is a detailed photo showing" # For summary-like analysis
|
195
|
+
|
196
|
+
# Generate analysis using BLIP
|
197
|
+
analysis_text = self._generate_text(pil_image, analysis_prompt)
|
198
|
+
|
199
|
+
return {
|
200
|
+
"task": "analyze",
|
201
|
+
"service": "BLIPVisionService",
|
202
|
+
"text": analysis_text,
|
203
|
+
"model_type": "BLIP",
|
204
|
+
"prompt_used": analysis_prompt,
|
205
|
+
"success": True
|
206
|
+
}
|
207
|
+
|
208
|
+
except Exception as e:
|
209
|
+
logger.error(f"Error analyzing image: {e}")
|
210
|
+
return {
|
211
|
+
"error": str(e),
|
212
|
+
"service": "BLIPVisionService",
|
213
|
+
"success": False
|
214
|
+
}
|
215
|
+
|
216
|
+
async def generate_caption(self, image: Union[str, BinaryIO]) -> Dict[str, Any]:
|
217
|
+
"""
|
218
|
+
Generate caption for image (Task 9 from notebook)
|
219
|
+
|
220
|
+
Args:
|
221
|
+
image: Image path or binary data
|
222
|
+
|
223
|
+
Returns:
|
224
|
+
Caption results
|
225
|
+
"""
|
226
|
+
try:
|
227
|
+
# Preprocess image
|
228
|
+
pil_image = self._preprocess_image(image)
|
229
|
+
|
230
|
+
# Generate caption
|
231
|
+
prompt = "This is a picture of" # Following notebook
|
232
|
+
caption = self._generate_text(pil_image, prompt)
|
233
|
+
|
234
|
+
return {
|
235
|
+
"task": "caption",
|
236
|
+
"service": "BLIPVisionService",
|
237
|
+
"caption": caption,
|
238
|
+
"model_type": "BLIP",
|
239
|
+
"success": True
|
240
|
+
}
|
241
|
+
|
242
|
+
except Exception as e:
|
243
|
+
logger.error(f"Error generating caption: {e}")
|
244
|
+
return {
|
245
|
+
"error": str(e),
|
246
|
+
"service": "BLIPVisionService",
|
247
|
+
"success": False
|
248
|
+
}
|
249
|
+
|
250
|
+
async def generate_summary(self, image: Union[str, BinaryIO]) -> Dict[str, Any]:
|
251
|
+
"""
|
252
|
+
Generate summary for image (Task 10 from notebook)
|
253
|
+
|
254
|
+
Args:
|
255
|
+
image: Image path or binary data
|
256
|
+
|
257
|
+
Returns:
|
258
|
+
Summary results
|
259
|
+
"""
|
260
|
+
try:
|
261
|
+
# Preprocess image
|
262
|
+
pil_image = self._preprocess_image(image)
|
263
|
+
|
264
|
+
# Generate summary
|
265
|
+
prompt = "This is a detailed photo showing" # Following notebook
|
266
|
+
summary = self._generate_text(pil_image, prompt)
|
267
|
+
|
268
|
+
return {
|
269
|
+
"task": "summary",
|
270
|
+
"service": "BLIPVisionService",
|
271
|
+
"summary": summary,
|
272
|
+
"model_type": "BLIP",
|
273
|
+
"success": True
|
274
|
+
}
|
275
|
+
|
276
|
+
except Exception as e:
|
277
|
+
logger.error(f"Error generating summary: {e}")
|
278
|
+
return {
|
279
|
+
"error": str(e),
|
280
|
+
"service": "BLIPVisionService",
|
281
|
+
"success": False
|
282
|
+
}
|
283
|
+
|
284
|
+
async def batch_generate(self,
|
285
|
+
images: List[Union[str, BinaryIO]],
|
286
|
+
task: str = "caption") -> Dict[str, Any]:
|
287
|
+
"""
|
288
|
+
Generate captions or summaries for multiple images
|
289
|
+
|
290
|
+
Args:
|
291
|
+
images: List of image paths or binary data
|
292
|
+
task: Task type ("caption" or "summary")
|
293
|
+
|
294
|
+
Returns:
|
295
|
+
Batch generation results
|
296
|
+
"""
|
297
|
+
try:
|
298
|
+
results = []
|
299
|
+
errors = []
|
300
|
+
|
301
|
+
for i, image in enumerate(images):
|
302
|
+
try:
|
303
|
+
if task == "caption":
|
304
|
+
result = await self.generate_caption(image)
|
305
|
+
elif task == "summary":
|
306
|
+
result = await self.generate_summary(image)
|
307
|
+
else:
|
308
|
+
raise ValueError(f"Unsupported task: {task}")
|
309
|
+
|
310
|
+
if result.get("success"):
|
311
|
+
results.append({
|
312
|
+
"index": i,
|
313
|
+
"image": str(image) if isinstance(image, str) else f"binary_image_{i}",
|
314
|
+
**result
|
315
|
+
})
|
316
|
+
else:
|
317
|
+
errors.append({
|
318
|
+
"index": i,
|
319
|
+
"image": str(image) if isinstance(image, str) else f"binary_image_{i}",
|
320
|
+
"error": result.get("error", "Unknown error")
|
321
|
+
})
|
322
|
+
|
323
|
+
except Exception as e:
|
324
|
+
errors.append({
|
325
|
+
"index": i,
|
326
|
+
"image": str(image) if isinstance(image, str) else f"binary_image_{i}",
|
327
|
+
"error": str(e)
|
328
|
+
})
|
329
|
+
|
330
|
+
return {
|
331
|
+
"task": f"batch_{task}",
|
332
|
+
"service": "BLIPVisionService",
|
333
|
+
"total_images": len(images),
|
334
|
+
"successful": len(results),
|
335
|
+
"failed": len(errors),
|
336
|
+
"results": results,
|
337
|
+
"errors": errors,
|
338
|
+
"success": True
|
339
|
+
}
|
340
|
+
|
341
|
+
except Exception as e:
|
342
|
+
logger.error(f"Error in batch generation: {e}")
|
343
|
+
return {
|
344
|
+
"error": str(e),
|
345
|
+
"service": "BLIPVisionService",
|
346
|
+
"success": False
|
347
|
+
}
|
348
|
+
|
349
|
+
def get_service_info(self) -> Dict[str, Any]:
|
350
|
+
"""Get service information"""
|
351
|
+
return {
|
352
|
+
"service_name": "BLIPVisionService",
|
353
|
+
"model_name": self.model_name,
|
354
|
+
"model_type": "BLIP",
|
355
|
+
"capabilities": ["describe", "analyze", "caption", "summary", "batch_generate"],
|
356
|
+
"model_loaded": self.model is not None,
|
357
|
+
"processor_loaded": self.processor is not None,
|
358
|
+
"dependencies_available": self.blip_components['available']
|
359
|
+
}
|
@@ -27,16 +27,22 @@ def get_image_data(image: Union[str, BinaryIO]) -> bytes:
|
|
27
27
|
return response.content
|
28
28
|
elif image.startswith('data:'):
|
29
29
|
# Data URL格式 (如 data:image/png;base64,...)
|
30
|
-
import base64
|
31
30
|
if 'base64,' in image:
|
32
31
|
base64_data = image.split('base64,')[1]
|
33
32
|
return base64.b64decode(base64_data)
|
34
33
|
else:
|
35
34
|
raise ValueError("Unsupported data URL format")
|
36
|
-
|
37
|
-
#
|
38
|
-
|
39
|
-
return
|
35
|
+
elif len(image) > 100 and not os.path.exists(image):
|
36
|
+
# 纯base64字符串 (没有data URL前缀)
|
37
|
+
try:
|
38
|
+
return base64.b64decode(image)
|
39
|
+
except Exception:
|
40
|
+
# 如果base64解码失败,则当作文件路径处理
|
41
|
+
pass
|
42
|
+
|
43
|
+
# 本地文件路径
|
44
|
+
with open(image, 'rb') as f:
|
45
|
+
return f.read()
|
40
46
|
elif hasattr(image, 'read'):
|
41
47
|
# 文件类对象
|
42
48
|
data = image.read()
|
@@ -53,25 +59,28 @@ def get_image_data(image: Union[str, BinaryIO]) -> bytes:
|
|
53
59
|
|
54
60
|
def compress_image(image_data: Union[bytes, BytesIO], max_size: int = 1024) -> bytes:
|
55
61
|
"""压缩图片以减小大小
|
56
|
-
|
62
|
+
|
57
63
|
Args:
|
58
64
|
image_data: 图片数据,可以是 bytes 或 BytesIO
|
59
65
|
max_size: 最大尺寸(像素)
|
60
|
-
|
66
|
+
|
61
67
|
Returns:
|
62
68
|
bytes: 压缩后的图片数据
|
63
69
|
"""
|
64
70
|
try:
|
71
|
+
# Ensure max_size is int (type safety)
|
72
|
+
max_size = int(max_size)
|
73
|
+
|
65
74
|
# 如果输入是 bytes,转换为 BytesIO
|
66
75
|
if isinstance(image_data, bytes):
|
67
76
|
image_data = BytesIO(image_data)
|
68
|
-
|
77
|
+
|
69
78
|
img = Image.open(image_data)
|
70
|
-
|
79
|
+
|
71
80
|
# 转换为 RGB 模式(如果需要)
|
72
81
|
if img.mode in ('RGBA', 'P'):
|
73
82
|
img = img.convert('RGB')
|
74
|
-
|
83
|
+
|
75
84
|
# 计算新尺寸,保持宽高比
|
76
85
|
ratio = max_size / max(img.size)
|
77
86
|
if ratio < 1:
|