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
@@ -1,766 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
ISA Vision Document Service
|
3
|
-
|
4
|
-
Specialized service for document analysis including:
|
5
|
-
- Table detection (Table Transformer Detection)
|
6
|
-
- Table structure recognition (Table Transformer Structure v1.1)
|
7
|
-
- OCR text extraction (PaddleOCR 3.0)
|
8
|
-
"""
|
9
|
-
|
10
|
-
import modal
|
11
|
-
import torch
|
12
|
-
import base64
|
13
|
-
import io
|
14
|
-
import numpy as np
|
15
|
-
from PIL import Image
|
16
|
-
from typing import Dict, List, Optional, Any
|
17
|
-
import time
|
18
|
-
import json
|
19
|
-
import os
|
20
|
-
import logging
|
21
|
-
|
22
|
-
# Define Modal application
|
23
|
-
app = modal.App("isa-vision-doc")
|
24
|
-
|
25
|
-
# Download document analysis models
|
26
|
-
def download_doc_models():
|
27
|
-
"""Download document analysis models"""
|
28
|
-
from huggingface_hub import snapshot_download
|
29
|
-
import subprocess
|
30
|
-
|
31
|
-
print("📦 Downloading document analysis models...")
|
32
|
-
os.makedirs("/models", exist_ok=True)
|
33
|
-
|
34
|
-
# Download Table Transformer Detection
|
35
|
-
try:
|
36
|
-
snapshot_download(
|
37
|
-
repo_id="microsoft/table-transformer-detection",
|
38
|
-
local_dir="/models/table-transformer-detection",
|
39
|
-
allow_patterns=["**/*.pt", "**/*.pth", "**/*.bin", "**/*.json", "**/*.safetensors"]
|
40
|
-
)
|
41
|
-
print("✅ Table Transformer Detection downloaded")
|
42
|
-
except Exception as e:
|
43
|
-
print(f"⚠️ Table Transformer Detection download failed: {e}")
|
44
|
-
|
45
|
-
# Download Table Transformer Structure Recognition v1.1
|
46
|
-
try:
|
47
|
-
snapshot_download(
|
48
|
-
repo_id="microsoft/table-transformer-structure-recognition-v1.1-all",
|
49
|
-
local_dir="/models/table-transformer-structure",
|
50
|
-
allow_patterns=["**/*.pt", "**/*.pth", "**/*.bin", "**/*.json", "**/*.safetensors"]
|
51
|
-
)
|
52
|
-
print("✅ Table Transformer Structure Recognition v1.1 downloaded")
|
53
|
-
except Exception as e:
|
54
|
-
print(f"⚠️ Table Transformer Structure Recognition download failed: {e}")
|
55
|
-
|
56
|
-
# Install PaddleOCR
|
57
|
-
try:
|
58
|
-
subprocess.run(["pip", "install", "paddleocr>=2.7.0", "--no-deps"], check=True)
|
59
|
-
print("✅ PaddleOCR installed")
|
60
|
-
except Exception as e:
|
61
|
-
print(f"⚠️ PaddleOCR install failed: {e}")
|
62
|
-
|
63
|
-
print("📦 Document analysis models download completed")
|
64
|
-
|
65
|
-
# Define Modal container image
|
66
|
-
image = (
|
67
|
-
modal.Image.debian_slim(python_version="3.11")
|
68
|
-
.apt_install([
|
69
|
-
# OpenGL and graphics libraries for PaddleOCR
|
70
|
-
"libgl1-mesa-glx",
|
71
|
-
"libglib2.0-0",
|
72
|
-
"libsm6",
|
73
|
-
"libxext6",
|
74
|
-
"libxrender-dev",
|
75
|
-
"libgomp1",
|
76
|
-
# Font support
|
77
|
-
"fontconfig",
|
78
|
-
"libfontconfig1",
|
79
|
-
"libfreetype6",
|
80
|
-
])
|
81
|
-
.pip_install([
|
82
|
-
# Core AI libraries
|
83
|
-
"torch>=2.0.0",
|
84
|
-
"torchvision",
|
85
|
-
"transformers>=4.35.0",
|
86
|
-
"huggingface_hub",
|
87
|
-
"accelerate",
|
88
|
-
|
89
|
-
# Image processing
|
90
|
-
"pillow>=10.0.1",
|
91
|
-
"opencv-python-headless",
|
92
|
-
"numpy>=1.24.3",
|
93
|
-
|
94
|
-
# OCR libraries - Latest stable versions
|
95
|
-
"paddleocr>=3.0.0",
|
96
|
-
"paddlepaddle>=3.0.0",
|
97
|
-
|
98
|
-
# HTTP libraries
|
99
|
-
"httpx>=0.26.0",
|
100
|
-
"requests",
|
101
|
-
|
102
|
-
# Utilities
|
103
|
-
"pydantic>=2.0.0",
|
104
|
-
"python-dotenv",
|
105
|
-
])
|
106
|
-
.run_function(download_doc_models)
|
107
|
-
.env({
|
108
|
-
"TRANSFORMERS_CACHE": "/models",
|
109
|
-
"FONTCONFIG_PATH": "/etc/fonts",
|
110
|
-
"KMP_DUPLICATE_LIB_OK": "TRUE",
|
111
|
-
"OMP_NUM_THREADS": "1",
|
112
|
-
"CUDA_VISIBLE_DEVICES": "0"
|
113
|
-
})
|
114
|
-
)
|
115
|
-
|
116
|
-
# Document Analysis Service
|
117
|
-
@app.cls(
|
118
|
-
gpu="T4",
|
119
|
-
image=image,
|
120
|
-
memory=16384, # 16GB RAM
|
121
|
-
timeout=1800, # 30 minutes
|
122
|
-
scaledown_window=60, # 1 minute idle timeout
|
123
|
-
min_containers=0, # Scale to zero when not in use
|
124
|
-
)
|
125
|
-
class DocumentAnalysisService:
|
126
|
-
"""
|
127
|
-
Document Analysis Service
|
128
|
-
|
129
|
-
Provides document analysis capabilities including:
|
130
|
-
- Table detection and structure recognition
|
131
|
-
- OCR text extraction
|
132
|
-
- Combined document parsing
|
133
|
-
"""
|
134
|
-
|
135
|
-
def __init__(self):
|
136
|
-
self.models = {}
|
137
|
-
self.logger = logging.getLogger(__name__)
|
138
|
-
|
139
|
-
@modal.enter()
|
140
|
-
def load_models(self):
|
141
|
-
"""Load document analysis models on container startup"""
|
142
|
-
print("🚀 Loading document analysis models...")
|
143
|
-
start_time = time.time()
|
144
|
-
|
145
|
-
try:
|
146
|
-
import sys
|
147
|
-
# Check system environment
|
148
|
-
print(f"🔧 System info:")
|
149
|
-
print(f" - Python version: {sys.version}")
|
150
|
-
print(f" - PyTorch version: {torch.__version__}")
|
151
|
-
print(f" - CUDA available: {torch.cuda.is_available()}")
|
152
|
-
if torch.cuda.is_available():
|
153
|
-
print(f" - CUDA version: {torch.version.cuda}")
|
154
|
-
print(f" - GPU count: {torch.cuda.device_count()}")
|
155
|
-
|
156
|
-
# Load table detection models
|
157
|
-
self._load_table_models()
|
158
|
-
|
159
|
-
# Load OCR models
|
160
|
-
self._load_ocr_models()
|
161
|
-
|
162
|
-
load_time = time.time() - start_time
|
163
|
-
print(f"✅ Document analysis models loaded in {load_time:.2f}s")
|
164
|
-
|
165
|
-
# Verify models are loaded
|
166
|
-
if not self.models.get('ocr'):
|
167
|
-
print("⚠️ OCR model failed to load - service will use fallback")
|
168
|
-
|
169
|
-
except Exception as e:
|
170
|
-
print(f"❌ Critical error during model loading: {e}")
|
171
|
-
import traceback
|
172
|
-
traceback.print_exc()
|
173
|
-
# Don't raise - let service start with degraded functionality
|
174
|
-
|
175
|
-
def _load_table_models(self):
|
176
|
-
"""Load table detection and structure recognition models"""
|
177
|
-
print("📊 Loading table analysis models...")
|
178
|
-
|
179
|
-
# TODO: Implement actual Table Transformer loading
|
180
|
-
# For now, we don't load these models to avoid mock data
|
181
|
-
print("⚠️ Table Transformer models not implemented yet")
|
182
|
-
print(" - Table detection will return empty results")
|
183
|
-
print(" - Table structure analysis will return empty results")
|
184
|
-
|
185
|
-
def _load_ocr_models(self):
|
186
|
-
"""Load OCR models"""
|
187
|
-
print("🔤 Loading OCR models...")
|
188
|
-
|
189
|
-
try:
|
190
|
-
import os
|
191
|
-
# Set environment variables to prevent conflicts and optimize performance
|
192
|
-
os.environ['KMP_DUPLICATE_LIB_OK'] = 'TRUE'
|
193
|
-
os.environ['OMP_NUM_THREADS'] = '1'
|
194
|
-
os.environ['MKLDNN_DISABLED'] = '1' # Disable MKLDNN to force GPU usage
|
195
|
-
|
196
|
-
from paddleocr import PaddleOCR
|
197
|
-
|
198
|
-
# Initialize PaddleOCR 3.0 with minimal configuration
|
199
|
-
# PaddleOCR 3.0 uses PP-OCRv5_server model by default which supports multiple languages
|
200
|
-
self.models['ocr'] = PaddleOCR(
|
201
|
-
use_angle_cls=True, # Enable text direction classification
|
202
|
-
lang='ch' # Chinese language (also supports English in the same model)
|
203
|
-
)
|
204
|
-
print("✅ PaddleOCR loaded successfully with official defaults")
|
205
|
-
print(f" - GPU available: {torch.cuda.is_available()}")
|
206
|
-
if torch.cuda.is_available():
|
207
|
-
print(f" - CUDA device: {torch.cuda.get_device_name(0)}")
|
208
|
-
print(f" - CUDA version: {torch.version.cuda}")
|
209
|
-
|
210
|
-
# Test OCR initialization
|
211
|
-
print("🔍 Testing OCR initialization...")
|
212
|
-
|
213
|
-
except Exception as e:
|
214
|
-
print(f"⚠️ PaddleOCR loading failed: {e}")
|
215
|
-
import traceback
|
216
|
-
traceback.print_exc()
|
217
|
-
self.models['ocr'] = None
|
218
|
-
|
219
|
-
@modal.method()
|
220
|
-
def detect_tables(self, image_b64: str) -> Dict[str, Any]:
|
221
|
-
"""
|
222
|
-
Detect tables in document image
|
223
|
-
|
224
|
-
Args:
|
225
|
-
image_b64: Base64 encoded image
|
226
|
-
|
227
|
-
Returns:
|
228
|
-
Table detection results
|
229
|
-
"""
|
230
|
-
start_time = time.time()
|
231
|
-
|
232
|
-
try:
|
233
|
-
# Decode image
|
234
|
-
image = self._decode_image(image_b64)
|
235
|
-
image_np = np.array(image)
|
236
|
-
|
237
|
-
# Perform table detection
|
238
|
-
tables = self._detect_tables_impl(image_np)
|
239
|
-
|
240
|
-
processing_time = time.time() - start_time
|
241
|
-
|
242
|
-
return {
|
243
|
-
'success': True,
|
244
|
-
'service': 'isa-vision-doc',
|
245
|
-
'function': 'table_detection',
|
246
|
-
'tables': tables,
|
247
|
-
'table_count': len(tables),
|
248
|
-
'processing_time': processing_time,
|
249
|
-
'model_info': {
|
250
|
-
'detector': 'Table Transformer Detection',
|
251
|
-
'gpu': 'T4'
|
252
|
-
}
|
253
|
-
}
|
254
|
-
|
255
|
-
except Exception as e:
|
256
|
-
self.logger.error(f"Table detection failed: {e}")
|
257
|
-
return {
|
258
|
-
'success': False,
|
259
|
-
'service': 'isa-vision-doc',
|
260
|
-
'function': 'table_detection',
|
261
|
-
'error': str(e),
|
262
|
-
'processing_time': time.time() - start_time
|
263
|
-
}
|
264
|
-
|
265
|
-
@modal.method()
|
266
|
-
def analyze_table_structure(self, image_b64: str, table_bbox: List[int] = None) -> Dict[str, Any]:
|
267
|
-
"""
|
268
|
-
Analyze table structure in image
|
269
|
-
|
270
|
-
Args:
|
271
|
-
image_b64: Base64 encoded image
|
272
|
-
table_bbox: Optional bounding box of table [x1, y1, x2, y2]
|
273
|
-
|
274
|
-
Returns:
|
275
|
-
Table structure analysis results
|
276
|
-
"""
|
277
|
-
start_time = time.time()
|
278
|
-
|
279
|
-
try:
|
280
|
-
# Decode image
|
281
|
-
image = self._decode_image(image_b64)
|
282
|
-
image_np = np.array(image)
|
283
|
-
|
284
|
-
# Crop to table region if bbox provided
|
285
|
-
if table_bbox:
|
286
|
-
x1, y1, x2, y2 = table_bbox
|
287
|
-
image_np = image_np[y1:y2, x1:x2]
|
288
|
-
|
289
|
-
# Analyze table structure
|
290
|
-
structure = self._analyze_table_structure_impl(image_np)
|
291
|
-
|
292
|
-
processing_time = time.time() - start_time
|
293
|
-
|
294
|
-
return {
|
295
|
-
'success': True,
|
296
|
-
'service': 'isa-vision-doc',
|
297
|
-
'function': 'table_structure',
|
298
|
-
'structure': structure,
|
299
|
-
'processing_time': processing_time,
|
300
|
-
'model_info': {
|
301
|
-
'analyzer': 'Table Transformer Structure Recognition v1.1',
|
302
|
-
'gpu': 'T4'
|
303
|
-
}
|
304
|
-
}
|
305
|
-
|
306
|
-
except Exception as e:
|
307
|
-
self.logger.error(f"Table structure analysis failed: {e}")
|
308
|
-
return {
|
309
|
-
'success': False,
|
310
|
-
'service': 'isa-vision-doc',
|
311
|
-
'function': 'table_structure',
|
312
|
-
'error': str(e),
|
313
|
-
'processing_time': time.time() - start_time
|
314
|
-
}
|
315
|
-
|
316
|
-
@modal.method()
|
317
|
-
def extract_text(self, image_b64: str, regions: List[Dict] = None) -> Dict[str, Any]:
|
318
|
-
"""
|
319
|
-
Extract text from document image using OCR
|
320
|
-
|
321
|
-
Args:
|
322
|
-
image_b64: Base64 encoded image
|
323
|
-
regions: Optional list of regions to focus OCR on
|
324
|
-
|
325
|
-
Returns:
|
326
|
-
OCR text extraction results
|
327
|
-
"""
|
328
|
-
start_time = time.time()
|
329
|
-
|
330
|
-
try:
|
331
|
-
# Decode image
|
332
|
-
image = self._decode_image(image_b64)
|
333
|
-
image_np = np.array(image)
|
334
|
-
|
335
|
-
# Perform OCR
|
336
|
-
text_results = self._extract_text_impl(image_np, regions)
|
337
|
-
|
338
|
-
processing_time = time.time() - start_time
|
339
|
-
|
340
|
-
return {
|
341
|
-
'success': True,
|
342
|
-
'service': 'isa-vision-doc',
|
343
|
-
'function': 'ocr',
|
344
|
-
'text_results': text_results,
|
345
|
-
'text_count': len(text_results),
|
346
|
-
'processing_time': processing_time,
|
347
|
-
'model_info': {
|
348
|
-
'ocr_engine': 'PaddleOCR 3.0',
|
349
|
-
'gpu': 'T4'
|
350
|
-
}
|
351
|
-
}
|
352
|
-
|
353
|
-
except Exception as e:
|
354
|
-
self.logger.error(f"OCR extraction failed: {e}")
|
355
|
-
return {
|
356
|
-
'success': False,
|
357
|
-
'service': 'isa-vision-doc',
|
358
|
-
'function': 'ocr',
|
359
|
-
'error': str(e),
|
360
|
-
'processing_time': time.time() - start_time
|
361
|
-
}
|
362
|
-
|
363
|
-
@modal.method()
|
364
|
-
def analyze_document_complete(self, image_b64: str) -> Dict[str, Any]:
|
365
|
-
"""
|
366
|
-
Complete document analysis: tables + structure + OCR
|
367
|
-
|
368
|
-
Args:
|
369
|
-
image_b64: Base64 encoded image
|
370
|
-
|
371
|
-
Returns:
|
372
|
-
Complete document analysis results
|
373
|
-
"""
|
374
|
-
start_time = time.time()
|
375
|
-
|
376
|
-
try:
|
377
|
-
# Decode image once for all operations
|
378
|
-
image = self._decode_image(image_b64)
|
379
|
-
image_np = np.array(image)
|
380
|
-
|
381
|
-
# Step 1: Detect tables
|
382
|
-
tables = self._detect_tables_impl(image_np)
|
383
|
-
table_detection_start = time.time()
|
384
|
-
table_result = {
|
385
|
-
'success': True,
|
386
|
-
'tables': tables,
|
387
|
-
'processing_time': time.time() - table_detection_start
|
388
|
-
}
|
389
|
-
|
390
|
-
# Step 2: Extract text
|
391
|
-
ocr_start = time.time()
|
392
|
-
text_results = self._extract_text_impl(image_np)
|
393
|
-
ocr_result = {
|
394
|
-
'success': True,
|
395
|
-
'text_results': text_results,
|
396
|
-
'processing_time': time.time() - ocr_start
|
397
|
-
}
|
398
|
-
|
399
|
-
# Step 3: Analyze table structures if tables found
|
400
|
-
structure_results = []
|
401
|
-
if table_result.get('success') and table_result.get('tables'):
|
402
|
-
for table in table_result['tables']:
|
403
|
-
if 'bbox' in table:
|
404
|
-
x1, y1, x2, y2 = table['bbox']
|
405
|
-
table_image = image_np[y1:y2, x1:x2]
|
406
|
-
structure = self._analyze_table_structure_impl(table_image)
|
407
|
-
structure_results.append(structure)
|
408
|
-
|
409
|
-
total_time = time.time() - start_time
|
410
|
-
|
411
|
-
return {
|
412
|
-
'success': True,
|
413
|
-
'service': 'isa-vision-doc',
|
414
|
-
'function': 'complete_analysis',
|
415
|
-
'total_execution_time': total_time,
|
416
|
-
'results': {
|
417
|
-
'tables': table_result.get('tables', []),
|
418
|
-
'table_structures': structure_results,
|
419
|
-
'text_extraction': ocr_result.get('text_results', [])
|
420
|
-
},
|
421
|
-
'summary': {
|
422
|
-
'tables_found': len(table_result.get('tables', [])),
|
423
|
-
'text_regions_found': len(ocr_result.get('text_results', [])),
|
424
|
-
'structures_analyzed': len(structure_results)
|
425
|
-
},
|
426
|
-
'performance_metrics': {
|
427
|
-
'table_detection_time': table_result.get('processing_time', 0),
|
428
|
-
'ocr_time': ocr_result.get('processing_time', 0),
|
429
|
-
'total_time': total_time,
|
430
|
-
'platform': 'modal'
|
431
|
-
}
|
432
|
-
}
|
433
|
-
|
434
|
-
except Exception as e:
|
435
|
-
self.logger.error(f"Complete document analysis failed: {e}")
|
436
|
-
return {
|
437
|
-
'success': False,
|
438
|
-
'service': 'isa-vision-doc',
|
439
|
-
'function': 'complete_analysis',
|
440
|
-
'error': str(e),
|
441
|
-
'total_execution_time': time.time() - start_time
|
442
|
-
}
|
443
|
-
|
444
|
-
def _detect_tables_impl(self, image_np: np.ndarray) -> List[Dict[str, Any]]:
|
445
|
-
"""Implementation of table detection"""
|
446
|
-
print("🔍 Table detection requested but not implemented")
|
447
|
-
print("⚠️ Table Transformer models need to be properly loaded")
|
448
|
-
|
449
|
-
# Return empty list since we don't have real table detection yet
|
450
|
-
# TODO: Implement actual Table Transformer Detection
|
451
|
-
return []
|
452
|
-
|
453
|
-
def _analyze_table_structure_impl(self, image_np: np.ndarray) -> Dict[str, Any]:
|
454
|
-
"""Implementation of table structure analysis"""
|
455
|
-
print("📊 Table structure analysis requested but not implemented")
|
456
|
-
print("⚠️ Table Transformer Structure Recognition models need to be properly loaded")
|
457
|
-
|
458
|
-
# Return empty structure since we don't have real table structure analysis yet
|
459
|
-
# TODO: Implement actual Table Transformer Structure Recognition
|
460
|
-
return {
|
461
|
-
'rows': 0,
|
462
|
-
'columns': 0,
|
463
|
-
'cells': [],
|
464
|
-
'confidence': 0.0
|
465
|
-
}
|
466
|
-
|
467
|
-
def _extract_text_impl(self, image_np: np.ndarray, regions: List[Dict] = None) -> List[Dict[str, Any]]:
|
468
|
-
"""Implementation of OCR text extraction"""
|
469
|
-
print(f"🔍 Debug: OCR model in models: {'ocr' in self.models}")
|
470
|
-
print(f"🔍 Debug: OCR model value: {self.models.get('ocr')}")
|
471
|
-
print(f"🔍 Debug: OCR model is not None: {self.models.get('ocr') is not None}")
|
472
|
-
|
473
|
-
if self.models.get('ocr') is not None:
|
474
|
-
try:
|
475
|
-
print("🔤 Using real PaddleOCR for text extraction...")
|
476
|
-
ocr = self.models['ocr']
|
477
|
-
print(f"🔍 Debug: OCR object type: {type(ocr)}")
|
478
|
-
|
479
|
-
# Ensure image is in correct format for PaddleOCR
|
480
|
-
if len(image_np.shape) == 3 and image_np.shape[2] == 3:
|
481
|
-
# Convert RGB to BGR for OpenCV/PaddleOCR
|
482
|
-
image_bgr = image_np[:, :, ::-1]
|
483
|
-
else:
|
484
|
-
image_bgr = image_np
|
485
|
-
|
486
|
-
print(f"🔍 Image shape for OCR: {image_bgr.shape}")
|
487
|
-
print(f"🔍 Image dtype: {image_bgr.dtype}")
|
488
|
-
print(f"🔍 Image min/max values: {image_bgr.min()}/{image_bgr.max()}")
|
489
|
-
|
490
|
-
# Save debug image to check what we're actually sending to OCR
|
491
|
-
try:
|
492
|
-
import cv2
|
493
|
-
cv2.imwrite('/tmp/debug_ocr_input.jpg', image_bgr)
|
494
|
-
print("🔍 Debug image saved to /tmp/debug_ocr_input.jpg")
|
495
|
-
except Exception as e:
|
496
|
-
print(f"⚠️ Failed to save debug image: {e}")
|
497
|
-
|
498
|
-
# Run PaddleOCR (angle classification is now built-in for v3.0)
|
499
|
-
print("🔍 Calling PaddleOCR...")
|
500
|
-
result = ocr.ocr(image_bgr)
|
501
|
-
print(f"🔍 PaddleOCR completed, raw result type: {type(result)}")
|
502
|
-
|
503
|
-
text_results = []
|
504
|
-
print(f"🔍 Checking result: result={bool(result)}, result length={len(result) if result else 0}")
|
505
|
-
if result:
|
506
|
-
print(f"🔍 First result element exists: {result[0] is not None}")
|
507
|
-
print(f"🔍 First result type: {type(result[0])}")
|
508
|
-
print(f"🔍 First result bool: {bool(result[0])}")
|
509
|
-
|
510
|
-
# Try to get length safely
|
511
|
-
try:
|
512
|
-
print(f"🔍 First result length: {len(result[0])}")
|
513
|
-
except Exception as e:
|
514
|
-
print(f"🔍 Cannot get length: {e}")
|
515
|
-
|
516
|
-
print(f"🔍 About to check if result[0] is truthy...")
|
517
|
-
if result and result[0]:
|
518
|
-
first_result = result[0]
|
519
|
-
|
520
|
-
# Debug: check what attributes the object actually has
|
521
|
-
print(f"🔍 Object attributes: {dir(first_result)}")
|
522
|
-
print(f"🔍 Has rec_texts: {hasattr(first_result, 'rec_texts')}")
|
523
|
-
|
524
|
-
# Check if it's PaddleOCR 3.0+ OCRResult object
|
525
|
-
if hasattr(first_result, 'rec_texts'):
|
526
|
-
print(f"🔍 Processing PaddleOCR 3.0+ OCRResult with {len(first_result.rec_texts)} text regions...")
|
527
|
-
|
528
|
-
rec_texts = first_result.rec_texts
|
529
|
-
rec_scores = first_result.rec_scores
|
530
|
-
rec_boxes = first_result.rec_boxes
|
531
|
-
|
532
|
-
for idx in range(len(rec_texts)):
|
533
|
-
text = rec_texts[idx]
|
534
|
-
confidence = rec_scores[idx]
|
535
|
-
bbox = rec_boxes[idx] # Should be [x1, y1, x2, y2]
|
536
|
-
|
537
|
-
text_results.append({
|
538
|
-
'id': f'text_{idx}',
|
539
|
-
'text': text,
|
540
|
-
'confidence': float(confidence),
|
541
|
-
'bbox': [int(bbox[0]), int(bbox[1]), int(bbox[2]), int(bbox[3])],
|
542
|
-
'center': [
|
543
|
-
(int(bbox[0]) + int(bbox[2])) // 2,
|
544
|
-
(int(bbox[1]) + int(bbox[3])) // 2
|
545
|
-
]
|
546
|
-
})
|
547
|
-
|
548
|
-
else:
|
549
|
-
print(f"🔍 Processing legacy format with {len(first_result)} text regions...")
|
550
|
-
for idx, line in enumerate(first_result):
|
551
|
-
bbox = line[0] # Bounding box points
|
552
|
-
text_info = line[1] # (text, confidence)
|
553
|
-
|
554
|
-
if text_info and len(text_info) >= 2:
|
555
|
-
# Convert bbox points to [x1, y1, x2, y2]
|
556
|
-
x_coords = [point[0] for point in bbox]
|
557
|
-
y_coords = [point[1] for point in bbox]
|
558
|
-
bbox_rect = [
|
559
|
-
int(min(x_coords)),
|
560
|
-
int(min(y_coords)),
|
561
|
-
int(max(x_coords)),
|
562
|
-
int(max(y_coords))
|
563
|
-
]
|
564
|
-
|
565
|
-
text_results.append({
|
566
|
-
'id': f'text_{idx}',
|
567
|
-
'text': text_info[0],
|
568
|
-
'confidence': text_info[1],
|
569
|
-
'bbox': bbox_rect,
|
570
|
-
'center': [
|
571
|
-
(bbox_rect[0] + bbox_rect[2]) // 2,
|
572
|
-
(bbox_rect[1] + bbox_rect[3]) // 2
|
573
|
-
]
|
574
|
-
})
|
575
|
-
|
576
|
-
print(f"✅ Real PaddleOCR extraction: {len(text_results)} text regions found")
|
577
|
-
return text_results
|
578
|
-
|
579
|
-
except Exception as e:
|
580
|
-
print(f"❌ PaddleOCR failed: {e}")
|
581
|
-
import traceback
|
582
|
-
traceback.print_exc()
|
583
|
-
|
584
|
-
# No fallback - return empty if PaddleOCR is not available
|
585
|
-
print("❌ PaddleOCR not available, returning empty results")
|
586
|
-
return []
|
587
|
-
|
588
|
-
@modal.method()
|
589
|
-
def health_check(self) -> Dict[str, Any]:
|
590
|
-
"""Health check endpoint"""
|
591
|
-
return {
|
592
|
-
'status': 'healthy',
|
593
|
-
'service': 'isa-vision-doc',
|
594
|
-
'models_loaded': list(self.models.keys()),
|
595
|
-
'capabilities': ['table_detection', 'table_structure', 'ocr'],
|
596
|
-
'timestamp': time.time(),
|
597
|
-
'gpu': 'T4'
|
598
|
-
}
|
599
|
-
|
600
|
-
def _decode_image(self, image_b64: str) -> Image.Image:
|
601
|
-
"""Decode base64 image"""
|
602
|
-
if image_b64.startswith('data:image'):
|
603
|
-
image_b64 = image_b64.split(',')[1]
|
604
|
-
|
605
|
-
image_data = base64.b64decode(image_b64)
|
606
|
-
return Image.open(io.BytesIO(image_data)).convert('RGB')
|
607
|
-
|
608
|
-
# Auto-registration function
|
609
|
-
@app.function()
|
610
|
-
async def register_service():
|
611
|
-
"""Auto-register this service in the model registry"""
|
612
|
-
try:
|
613
|
-
import sys
|
614
|
-
from pathlib import Path
|
615
|
-
|
616
|
-
# Add project root to path for imports
|
617
|
-
project_root = Path(__file__).parent.parent.parent.parent
|
618
|
-
sys.path.insert(0, str(project_root))
|
619
|
-
|
620
|
-
try:
|
621
|
-
from isa_model.core.model_manager import ModelManager
|
622
|
-
from isa_model.core.model_repo import ModelType, ModelCapability
|
623
|
-
from isa_model.core.service_registry import ServiceRegistry
|
624
|
-
from isa_model.core.types import ServiceType, DeploymentPlatform, ServiceStatus, ResourceRequirements
|
625
|
-
from isa_model.core.model_service import ModelService
|
626
|
-
except ImportError:
|
627
|
-
# Fallback if import fails in Modal environment
|
628
|
-
print("⚠️ Could not import required modules - registration skipped")
|
629
|
-
return {"success": False, "error": "Required modules not available"}
|
630
|
-
|
631
|
-
# Use ModelManager to register this service
|
632
|
-
model_manager = ModelManager()
|
633
|
-
|
634
|
-
# 1. First register the underlying model (backward compatibility)
|
635
|
-
model_success = model_manager.registry.register_model(
|
636
|
-
model_id="isa-vision-doc-service",
|
637
|
-
model_type=ModelType.VISION,
|
638
|
-
capabilities=[
|
639
|
-
ModelCapability.TABLE_DETECTION,
|
640
|
-
ModelCapability.TABLE_STRUCTURE_RECOGNITION,
|
641
|
-
ModelCapability.OCR,
|
642
|
-
ModelCapability.IMAGE_ANALYSIS
|
643
|
-
],
|
644
|
-
metadata={
|
645
|
-
"description": "ISA Vision Document Analysis Service with table detection, structure recognition, and OCR",
|
646
|
-
"service_name": "isa-vision-doc",
|
647
|
-
"service_type": "modal",
|
648
|
-
"deployment_type": "modal",
|
649
|
-
"endpoint": "https://isa-vision-doc.modal.run",
|
650
|
-
"underlying_models": [
|
651
|
-
"microsoft/table-transformer-detection",
|
652
|
-
"microsoft/table-transformer-structure-recognition-v1.1-all",
|
653
|
-
"PaddleOCR 3.0"
|
654
|
-
],
|
655
|
-
"gpu_requirement": "T4",
|
656
|
-
"memory_mb": 16384,
|
657
|
-
"auto_registered": True,
|
658
|
-
"registered_by": "isa_vision_doc_service.py",
|
659
|
-
"is_service": True, # Mark this as a service, not a raw model
|
660
|
-
"capabilities_details": {
|
661
|
-
"table_detection": "Microsoft Table Transformer Detection",
|
662
|
-
"table_structure": "Microsoft Table Transformer Structure Recognition v1.1",
|
663
|
-
"ocr": "PaddleOCR 3.0 with Chinese/English support"
|
664
|
-
}
|
665
|
-
}
|
666
|
-
)
|
667
|
-
|
668
|
-
# 2. Register as a deployed service in the ServiceRegistry (MaaS platform)
|
669
|
-
service_success = False
|
670
|
-
try:
|
671
|
-
service_registry = ServiceRegistry(model_manager.registry)
|
672
|
-
|
673
|
-
# Create ModelService instance
|
674
|
-
service = ModelService(
|
675
|
-
service_id="isa-vision-doc-modal-001",
|
676
|
-
service_name="isa_vision_doc",
|
677
|
-
model_id="isa-vision-doc-service",
|
678
|
-
deployment_platform=DeploymentPlatform.MODAL,
|
679
|
-
service_type=ServiceType.VISION,
|
680
|
-
status=ServiceStatus.HEALTHY,
|
681
|
-
inference_endpoint="https://isa-vision-doc.modal.run/analyze_document_complete",
|
682
|
-
health_endpoint="https://isa-vision-doc.modal.run/health_check",
|
683
|
-
capabilities=["table_detection", "table_structure_recognition", "ocr", "image_analysis"],
|
684
|
-
resource_requirements=ResourceRequirements(
|
685
|
-
gpu_type="T4",
|
686
|
-
memory_mb=16384,
|
687
|
-
cpu_cores=4,
|
688
|
-
min_replicas=0,
|
689
|
-
max_replicas=5
|
690
|
-
),
|
691
|
-
metadata={
|
692
|
-
"description": "ISA Vision Document Analysis Service with table detection, structure recognition, and OCR",
|
693
|
-
"underlying_models": [
|
694
|
-
"microsoft/table-transformer-detection",
|
695
|
-
"microsoft/table-transformer-structure-recognition-v1.1-all",
|
696
|
-
"PaddleOCR 3.0"
|
697
|
-
],
|
698
|
-
"auto_scaling": True,
|
699
|
-
"scale_to_zero": True,
|
700
|
-
"platform": "modal",
|
701
|
-
"registered_by": "isa_vision_doc_service.py"
|
702
|
-
}
|
703
|
-
)
|
704
|
-
|
705
|
-
# Register in ServiceRegistry
|
706
|
-
service_success = await service_registry.register_service(service)
|
707
|
-
|
708
|
-
if service_success:
|
709
|
-
print("✅ Service registered in MaaS platform ServiceRegistry")
|
710
|
-
else:
|
711
|
-
print("⚠️ ServiceRegistry registration failed")
|
712
|
-
|
713
|
-
except Exception as e:
|
714
|
-
print(f"⚠️ ServiceRegistry registration error: {e}")
|
715
|
-
|
716
|
-
if model_success:
|
717
|
-
print("✅ Model registry registration successful")
|
718
|
-
else:
|
719
|
-
print("⚠️ Model registry registration failed")
|
720
|
-
|
721
|
-
overall_success = model_success and service_success
|
722
|
-
return {
|
723
|
-
"success": overall_success,
|
724
|
-
"model_registry": model_success,
|
725
|
-
"service_registry": service_success
|
726
|
-
}
|
727
|
-
|
728
|
-
except Exception as e:
|
729
|
-
print(f"❌ Auto-registration error: {e}")
|
730
|
-
return {"success": False, "error": str(e)}
|
731
|
-
|
732
|
-
# Quick deployment function
|
733
|
-
@app.function()
|
734
|
-
def deploy_service():
|
735
|
-
"""Deploy this service instantly"""
|
736
|
-
import subprocess
|
737
|
-
import os
|
738
|
-
|
739
|
-
print("🚀 Deploying ISA Vision Document Service...")
|
740
|
-
try:
|
741
|
-
# Get the current file path
|
742
|
-
current_file = __file__
|
743
|
-
|
744
|
-
# Run modal deploy command
|
745
|
-
result = subprocess.run(
|
746
|
-
["modal", "deploy", current_file],
|
747
|
-
capture_output=True,
|
748
|
-
text=True,
|
749
|
-
check=True
|
750
|
-
)
|
751
|
-
|
752
|
-
print("✅ Deployment completed successfully!")
|
753
|
-
print(f"📝 Output: {result.stdout}")
|
754
|
-
return {"success": True, "output": result.stdout}
|
755
|
-
|
756
|
-
except subprocess.CalledProcessError as e:
|
757
|
-
print(f"❌ Deployment failed: {e}")
|
758
|
-
print(f"📝 Error: {e.stderr}")
|
759
|
-
return {"success": False, "error": str(e), "stderr": e.stderr}
|
760
|
-
|
761
|
-
if __name__ == "__main__":
|
762
|
-
print("🚀 ISA Vision Document Service - Modal Deployment")
|
763
|
-
print("Deploy with: modal deploy isa_vision_doc_service.py")
|
764
|
-
print("Or call: modal run isa_vision_doc_service.py::deploy_service")
|
765
|
-
print("Note: Requires T4 GPU and 16GB+ RAM for optimal performance")
|
766
|
-
print("\n📝 Service will auto-register in model registry upon deployment")
|