isa-model 0.3.9__py3-none-any.whl → 0.4.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. isa_model/__init__.py +1 -1
  2. isa_model/client.py +732 -565
  3. isa_model/core/cache/redis_cache.py +401 -0
  4. isa_model/core/config/config_manager.py +53 -10
  5. isa_model/core/config.py +1 -1
  6. isa_model/core/database/__init__.py +1 -0
  7. isa_model/core/database/migrations.py +277 -0
  8. isa_model/core/database/supabase_client.py +123 -0
  9. isa_model/core/models/__init__.py +37 -0
  10. isa_model/core/models/model_billing_tracker.py +60 -88
  11. isa_model/core/models/model_manager.py +36 -18
  12. isa_model/core/models/model_repo.py +44 -38
  13. isa_model/core/models/model_statistics_tracker.py +234 -0
  14. isa_model/core/models/model_storage.py +0 -1
  15. isa_model/core/models/model_version_manager.py +959 -0
  16. isa_model/core/pricing_manager.py +2 -249
  17. isa_model/core/resilience/circuit_breaker.py +366 -0
  18. isa_model/core/security/secrets.py +358 -0
  19. isa_model/core/services/__init__.py +2 -4
  20. isa_model/core/services/intelligent_model_selector.py +101 -370
  21. isa_model/core/storage/hf_storage.py +1 -1
  22. isa_model/core/types.py +7 -0
  23. isa_model/deployment/cloud/modal/isa_audio_chatTTS_service.py +520 -0
  24. isa_model/deployment/cloud/modal/isa_audio_fish_service.py +0 -0
  25. isa_model/deployment/cloud/modal/isa_audio_openvoice_service.py +758 -0
  26. isa_model/deployment/cloud/modal/isa_audio_service_v2.py +1044 -0
  27. isa_model/deployment/cloud/modal/isa_embed_rerank_service.py +296 -0
  28. isa_model/deployment/cloud/modal/isa_video_hunyuan_service.py +423 -0
  29. isa_model/deployment/cloud/modal/isa_vision_ocr_service.py +519 -0
  30. isa_model/deployment/cloud/modal/isa_vision_qwen25_service.py +709 -0
  31. isa_model/deployment/cloud/modal/isa_vision_table_service.py +467 -323
  32. isa_model/deployment/cloud/modal/isa_vision_ui_service.py +607 -180
  33. isa_model/deployment/cloud/modal/isa_vision_ui_service_optimized.py +660 -0
  34. isa_model/deployment/core/deployment_manager.py +6 -4
  35. isa_model/deployment/services/auto_hf_modal_deployer.py +894 -0
  36. isa_model/eval/benchmarks/__init__.py +27 -0
  37. isa_model/eval/benchmarks/multimodal_datasets.py +460 -0
  38. isa_model/eval/benchmarks.py +244 -12
  39. isa_model/eval/evaluators/__init__.py +8 -2
  40. isa_model/eval/evaluators/audio_evaluator.py +727 -0
  41. isa_model/eval/evaluators/embedding_evaluator.py +742 -0
  42. isa_model/eval/evaluators/vision_evaluator.py +564 -0
  43. isa_model/eval/example_evaluation.py +395 -0
  44. isa_model/eval/factory.py +272 -5
  45. isa_model/eval/isa_benchmarks.py +700 -0
  46. isa_model/eval/isa_integration.py +582 -0
  47. isa_model/eval/metrics.py +159 -6
  48. isa_model/eval/tests/unit/test_basic.py +396 -0
  49. isa_model/inference/ai_factory.py +44 -8
  50. isa_model/inference/services/audio/__init__.py +21 -0
  51. isa_model/inference/services/audio/base_realtime_service.py +225 -0
  52. isa_model/inference/services/audio/isa_tts_service.py +0 -0
  53. isa_model/inference/services/audio/openai_realtime_service.py +320 -124
  54. isa_model/inference/services/audio/openai_stt_service.py +32 -6
  55. isa_model/inference/services/base_service.py +17 -1
  56. isa_model/inference/services/embedding/__init__.py +13 -0
  57. isa_model/inference/services/embedding/base_embed_service.py +111 -8
  58. isa_model/inference/services/embedding/isa_embed_service.py +305 -0
  59. isa_model/inference/services/embedding/openai_embed_service.py +2 -4
  60. isa_model/inference/services/embedding/tests/test_embedding.py +222 -0
  61. isa_model/inference/services/img/__init__.py +2 -2
  62. isa_model/inference/services/img/base_image_gen_service.py +24 -7
  63. isa_model/inference/services/img/replicate_image_gen_service.py +84 -422
  64. isa_model/inference/services/img/services/replicate_face_swap.py +193 -0
  65. isa_model/inference/services/img/services/replicate_flux.py +226 -0
  66. isa_model/inference/services/img/services/replicate_flux_kontext.py +219 -0
  67. isa_model/inference/services/img/services/replicate_sticker_maker.py +249 -0
  68. isa_model/inference/services/img/tests/test_img_client.py +297 -0
  69. isa_model/inference/services/llm/base_llm_service.py +30 -6
  70. isa_model/inference/services/llm/helpers/llm_adapter.py +63 -9
  71. isa_model/inference/services/llm/ollama_llm_service.py +2 -1
  72. isa_model/inference/services/llm/openai_llm_service.py +652 -55
  73. isa_model/inference/services/llm/yyds_llm_service.py +2 -1
  74. isa_model/inference/services/vision/__init__.py +5 -5
  75. isa_model/inference/services/vision/base_vision_service.py +118 -185
  76. isa_model/inference/services/vision/helpers/image_utils.py +11 -5
  77. isa_model/inference/services/vision/isa_vision_service.py +573 -0
  78. isa_model/inference/services/vision/tests/test_ocr_client.py +284 -0
  79. isa_model/serving/api/fastapi_server.py +88 -16
  80. isa_model/serving/api/middleware/auth.py +311 -0
  81. isa_model/serving/api/middleware/security.py +278 -0
  82. isa_model/serving/api/routes/analytics.py +486 -0
  83. isa_model/serving/api/routes/deployments.py +339 -0
  84. isa_model/serving/api/routes/evaluations.py +579 -0
  85. isa_model/serving/api/routes/logs.py +430 -0
  86. isa_model/serving/api/routes/settings.py +582 -0
  87. isa_model/serving/api/routes/unified.py +324 -165
  88. isa_model/serving/api/startup.py +304 -0
  89. isa_model/serving/modal_proxy_server.py +249 -0
  90. isa_model/training/__init__.py +100 -6
  91. isa_model/training/core/__init__.py +4 -1
  92. isa_model/training/examples/intelligent_training_example.py +281 -0
  93. isa_model/training/intelligent/__init__.py +25 -0
  94. isa_model/training/intelligent/decision_engine.py +643 -0
  95. isa_model/training/intelligent/intelligent_factory.py +888 -0
  96. isa_model/training/intelligent/knowledge_base.py +751 -0
  97. isa_model/training/intelligent/resource_optimizer.py +839 -0
  98. isa_model/training/intelligent/task_classifier.py +576 -0
  99. isa_model/training/storage/__init__.py +24 -0
  100. isa_model/training/storage/core_integration.py +439 -0
  101. isa_model/training/storage/training_repository.py +552 -0
  102. isa_model/training/storage/training_storage.py +628 -0
  103. {isa_model-0.3.9.dist-info → isa_model-0.4.0.dist-info}/METADATA +13 -1
  104. isa_model-0.4.0.dist-info/RECORD +182 -0
  105. isa_model/deployment/cloud/modal/isa_vision_doc_service.py +0 -766
  106. isa_model/deployment/cloud/modal/register_models.py +0 -321
  107. isa_model/inference/adapter/unified_api.py +0 -248
  108. isa_model/inference/services/helpers/stacked_config.py +0 -148
  109. isa_model/inference/services/img/flux_professional_service.py +0 -603
  110. isa_model/inference/services/img/helpers/base_stacked_service.py +0 -274
  111. isa_model/inference/services/others/table_transformer_service.py +0 -61
  112. isa_model/inference/services/vision/doc_analysis_service.py +0 -640
  113. isa_model/inference/services/vision/helpers/base_stacked_service.py +0 -274
  114. isa_model/inference/services/vision/ui_analysis_service.py +0 -823
  115. isa_model/scripts/inference_tracker.py +0 -283
  116. isa_model/scripts/mlflow_manager.py +0 -379
  117. isa_model/scripts/model_registry.py +0 -465
  118. isa_model/scripts/register_models.py +0 -370
  119. isa_model/scripts/register_models_with_embeddings.py +0 -510
  120. isa_model/scripts/start_mlflow.py +0 -95
  121. isa_model/scripts/training_tracker.py +0 -257
  122. isa_model-0.3.9.dist-info/RECORD +0 -138
  123. {isa_model-0.3.9.dist-info → isa_model-0.4.0.dist-info}/WHEEL +0 -0
  124. {isa_model-0.3.9.dist-info → isa_model-0.4.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,284 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+
4
+ """
5
+ Test OCR Client using ISA Model Client
6
+ Tests the SuryaOCR service for text extraction through the unified client.
7
+ """
8
+
9
+ import asyncio
10
+ import logging
11
+ from typing import Dict, Any
12
+
13
+ from isa_model.client import ISAModelClient
14
+
15
+ # Set up logging
16
+ logging.basicConfig(level=logging.INFO)
17
+ logger = logging.getLogger(__name__)
18
+
19
+ class OCRTester:
20
+ """Test client for SuryaOCR service using ISA Model Client"""
21
+
22
+ def __init__(self):
23
+ self.client = ISAModelClient()
24
+
25
+ # Test configuration for OCR service
26
+ self.test_config = {
27
+ "model": "isa-suryaocr",
28
+ "provider": "isa",
29
+ "task": "extract",
30
+ "input_image": "isa_model/inference/services/vision/tests/contract.png"
31
+ }
32
+
33
+ async def test_ocr_extraction(self) -> Dict[str, Any]:
34
+ """Test OCR text extraction from contract image using unified client"""
35
+ logger.info("Testing OCR text extraction via unified client...")
36
+
37
+ try:
38
+ config = self.test_config
39
+
40
+ result = await self.client.invoke(
41
+ input_data=config["input_image"],
42
+ task=config["task"],
43
+ service_type="vision",
44
+ model=config["model"],
45
+ provider=config["provider"],
46
+ languages=["en", "zh"]
47
+ )
48
+
49
+ if result.get("success"):
50
+ response = result["result"]
51
+ logger.info(f"OCR extraction successful")
52
+
53
+ # Get extracted text
54
+ extracted_text = response.get('text', '')
55
+ text_length = len(extracted_text)
56
+ logger.info(f"Text extracted: {text_length} characters")
57
+
58
+ # Get cost information
59
+ cost = response.get('metadata', {}).get('billing', {}).get('estimated_cost_usd', 0)
60
+ logger.info(f"Cost: ${cost:.6f}")
61
+
62
+ # Log first 200 characters of extracted text for verification
63
+ if extracted_text:
64
+ preview_text = extracted_text[:200] + "..." if text_length > 200 else extracted_text
65
+ logger.info(f"Text preview: {preview_text}")
66
+
67
+ return {
68
+ "status": "success",
69
+ "result": response,
70
+ "metadata": result.get("metadata", {}),
71
+ "text_length": text_length,
72
+ "cost": cost
73
+ }
74
+ else:
75
+ error_msg = result.get("error", "Unknown error")
76
+ logger.error(f"OCR extraction failed: {error_msg}")
77
+ return {"status": "error", "error": error_msg}
78
+
79
+ except Exception as e:
80
+ logger.error(f"OCR extraction failed with exception: {e}")
81
+ return {"status": "error", "error": str(e)}
82
+
83
+ async def test_direct_vision_service(self) -> Dict[str, Any]:
84
+ """Test OCR using direct ISA vision service call"""
85
+ logger.info("Testing direct ISA vision service OCR...")
86
+
87
+ try:
88
+ from isa_model.inference import AIFactory
89
+
90
+ # Get ISA vision service directly
91
+ vision = AIFactory().get_vision(provider="isa")
92
+
93
+ # Extract text using SuryaOCR
94
+ result = await vision.extract_text(
95
+ self.test_config["input_image"],
96
+ languages=["en", "zh"]
97
+ )
98
+
99
+ if result.get('success'):
100
+ logger.info(f"Direct SuryaOCR successful")
101
+
102
+ # Get extracted text from text_results array
103
+ text_results = result.get('text_results', [])
104
+ extracted_text = ' '.join([item.get('text', '') for item in text_results])
105
+ text_length = len(extracted_text)
106
+ logger.info(f"Text extracted: {text_length} characters from {len(text_results)} detected regions")
107
+
108
+ # Get cost information
109
+ cost = result.get('billing', {}).get('estimated_cost_usd', 0)
110
+ logger.info(f"Cost: ${cost:.6f}")
111
+
112
+ # Count Chinese and English characters
113
+ chinese_chars = sum(1 for char in extracted_text if '\u4e00' <= char <= '\u9fff')
114
+ english_chars = sum(1 for char in extracted_text if char.isalpha() and ord(char) < 256)
115
+ logger.info(f"Chinese characters: {chinese_chars}, English characters: {english_chars}")
116
+
117
+ # Log text preview (first few items)
118
+ if text_results:
119
+ sample_texts = [item.get('text', '') for item in text_results[:5]]
120
+ logger.info(f"Sample extracted text: {sample_texts}")
121
+
122
+ return {
123
+ "status": "success",
124
+ "result": result,
125
+ "text_length": text_length,
126
+ "cost": cost
127
+ }
128
+ else:
129
+ error_msg = result.get("error", "Unknown error")
130
+ logger.error(f"Direct SuryaOCR failed: {error_msg}")
131
+ return {"status": "error", "error": error_msg}
132
+
133
+ except Exception as e:
134
+ logger.error(f"Direct SuryaOCR failed with exception: {e}")
135
+ return {"status": "error", "error": str(e)}
136
+
137
+ async def test_chinese_and_english_ocr(self) -> Dict[str, Any]:
138
+ """Test OCR with Chinese and English language support"""
139
+ logger.info("Testing Chinese and English OCR support...")
140
+
141
+ try:
142
+ from isa_model.inference import AIFactory
143
+
144
+ vision = AIFactory().get_vision(provider="isa")
145
+
146
+ # Test with both Chinese and English languages
147
+ result = await vision.extract_text(
148
+ self.test_config["input_image"],
149
+ languages=["zh", "en"] # Chinese first, then English
150
+ )
151
+
152
+ if result.get('success'):
153
+ logger.info(f"Multi-language OCR successful")
154
+
155
+ extracted_text = result.get('text', '')
156
+ text_length = len(extracted_text)
157
+ logger.info(f"Text length: {text_length}")
158
+
159
+ # Check for Chinese characters
160
+ chinese_chars = sum(1 for char in extracted_text if '\u4e00' <= char <= '\u9fff')
161
+ english_chars = sum(1 for char in extracted_text if char.isalpha() and ord(char) < 256)
162
+
163
+ logger.info(f"Chinese characters detected: {chinese_chars}")
164
+ logger.info(f"English characters detected: {english_chars}")
165
+
166
+ # Get cost
167
+ cost = result.get('billing', {}).get('estimated_cost_usd', 0)
168
+ logger.info(f"Cost: ${cost:.6f}")
169
+
170
+ return {
171
+ "status": "success",
172
+ "result": result,
173
+ "text_length": text_length,
174
+ "chinese_chars": chinese_chars,
175
+ "english_chars": english_chars,
176
+ "cost": cost
177
+ }
178
+ else:
179
+ error_msg = result.get("error", "Unknown error")
180
+ logger.error(f"Multi-language OCR failed: {error_msg}")
181
+ return {"status": "error", "error": error_msg}
182
+
183
+ except Exception as e:
184
+ logger.error(f"Multi-language OCR failed with exception: {e}")
185
+ return {"status": "error", "error": str(e)}
186
+
187
+ async def test_all_ocr_methods(self) -> Dict[str, Dict[str, Any]]:
188
+ """Test OCR functionality"""
189
+ logger.info("Starting SuryaOCR test using ISA Model Client...")
190
+
191
+ results = {}
192
+
193
+ # Test only the direct vision service (most comprehensive)
194
+ tests = [
195
+ ("suryaocr_extraction", self.test_direct_vision_service)
196
+ ]
197
+
198
+ for test_name, test_func in tests:
199
+ logger.info(f"\n{'='*50}")
200
+ logger.info(f"Running test: {test_name}")
201
+ logger.info(f"{'='*50}")
202
+
203
+ try:
204
+ result = await test_func()
205
+ results[test_name] = result
206
+
207
+ if result.get("status") == "success":
208
+ logger.info(f" {test_name} PASSED")
209
+ else:
210
+ logger.error(f"L {test_name} FAILED: {result.get('error', 'Unknown error')}")
211
+
212
+ except Exception as e:
213
+ logger.error(f"L {test_name} FAILED with exception: {e}")
214
+ results[test_name] = {"status": "error", "error": str(e)}
215
+
216
+ # Summary
217
+ logger.info(f"\n{'='*50}")
218
+ logger.info("TEST SUMMARY")
219
+ logger.info(f"{'='*50}")
220
+
221
+ passed = sum(1 for r in results.values() if r.get("status") == "success")
222
+ total = len(results)
223
+
224
+ logger.info(f"Passed: {passed}/{total}")
225
+
226
+ for test_name, result in results.items():
227
+ status = " PASS" if result.get("status") == "success" else "L FAIL"
228
+ logger.info(f"{test_name}: {status}")
229
+
230
+ return results
231
+
232
+ async def get_service_health(self) -> Dict[str, Any]:
233
+ """Get health status of the client and services"""
234
+ logger.info("Checking service health...")
235
+
236
+ try:
237
+ health = await self.client.health_check()
238
+ return health
239
+ except Exception as e:
240
+ logger.error(f"Health check failed: {e}")
241
+ return {"status": "error", "error": str(e)}
242
+
243
+ async def main():
244
+ """Main test function"""
245
+ tester = OCRTester()
246
+
247
+ # Get service health
248
+ logger.info("Checking service health...")
249
+ health = await tester.get_service_health()
250
+ logger.info(f"Service health: {health}")
251
+
252
+ # Run all tests
253
+ results = await tester.test_all_ocr_methods()
254
+
255
+ # Calculate total cost
256
+ total_cost = 0.0
257
+ for test_name, result in results.items():
258
+ if result.get("status") == "success":
259
+ cost = result.get("cost", 0.0)
260
+ total_cost += cost
261
+
262
+ logger.info(f"\nTotal cost for all OCR tests: ${total_cost:.6f}")
263
+
264
+ # Summary of text extraction results
265
+ logger.info(f"\n{'='*50}")
266
+ logger.info("TEXT EXTRACTION SUMMARY")
267
+ logger.info(f"{'='*50}")
268
+
269
+ for test_name, result in results.items():
270
+ if result.get("status") == "success":
271
+ text_length = result.get("text_length", 0)
272
+ cost = result.get("cost", 0)
273
+ logger.info(f"{test_name}: {text_length} chars extracted, ${cost:.6f}")
274
+
275
+ # Show language breakdown if available
276
+ if "chinese_chars" in result and "english_chars" in result:
277
+ logger.info(f" - Chinese: {result['chinese_chars']} chars")
278
+ logger.info(f" - English: {result['english_chars']} chars")
279
+
280
+ return results
281
+
282
+ if __name__ == "__main__":
283
+ # Run the tests
284
+ results = asyncio.run(main())
@@ -4,18 +4,56 @@ FastAPI Server for ISA Model Serving
4
4
  Main FastAPI application that serves model inference endpoints
5
5
  """
6
6
 
7
- from fastapi import FastAPI, Request
7
+ from fastapi import FastAPI, Request, HTTPException, Depends
8
8
  from fastapi.middleware.cors import CORSMiddleware
9
+ from fastapi.middleware.trustedhost import TrustedHostMiddleware
9
10
  from fastapi.responses import JSONResponse
11
+ from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
12
+ from fastapi.staticfiles import StaticFiles
10
13
  import time
11
14
  import logging
12
- from typing import Dict, Any
15
+ import os
16
+ from typing import Dict, Any, Optional
13
17
 
14
- from .routes import ui_analysis, vision, llm, health, unified
18
+ from .routes import health, unified, deployments, logs, analytics, settings, evaluations
15
19
  from .middleware.request_logger import RequestLoggerMiddleware
20
+ from .middleware.security import setup_security_middleware, check_redis_health
21
+ from .startup import run_startup_initialization
16
22
 
17
23
  logger = logging.getLogger(__name__)
18
24
 
25
+ def configure_logging():
26
+ """Configure logging based on environment variables"""
27
+ log_level = os.getenv('LOG_LEVEL', 'INFO').upper()
28
+ verbose_logging = os.getenv('VERBOSE_LOGGING', 'false').lower() == 'true'
29
+
30
+ # Set log level
31
+ level = getattr(logging, log_level, logging.INFO)
32
+
33
+ # Configure format
34
+ if verbose_logging:
35
+ log_format = '%(asctime)s - %(name)s - %(levelname)s - %(funcName)s:%(lineno)d - %(message)s'
36
+ else:
37
+ log_format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
38
+
39
+ # Configure root logger
40
+ logging.basicConfig(
41
+ level=level,
42
+ format=log_format,
43
+ datefmt='%Y-%m-%d %H:%M:%S',
44
+ force=True # Override existing configuration
45
+ )
46
+
47
+ # Set uvicorn logger level to match
48
+ uvicorn_logger = logging.getLogger("uvicorn")
49
+ uvicorn_logger.setLevel(level)
50
+
51
+ # Set app logger level
52
+ app_logger = logging.getLogger("isa_model")
53
+ app_logger.setLevel(level)
54
+
55
+ logger.info(f"Logging configured - Level: {log_level}, Verbose: {verbose_logging}")
56
+
19
57
  def create_app(config: Dict[str, Any] = None) -> FastAPI:
20
58
  """
21
59
  Create and configure FastAPI application
@@ -26,6 +64,9 @@ def create_app(config: Dict[str, Any] = None) -> FastAPI:
26
64
  Returns:
27
65
  Configured FastAPI application
28
66
  """
67
+ # Configure logging first
68
+ configure_logging()
69
+
29
70
  app = FastAPI(
30
71
  title="ISA Model Serving API",
31
72
  description="High-performance model inference API",
@@ -34,14 +75,9 @@ def create_app(config: Dict[str, Any] = None) -> FastAPI:
34
75
  redoc_url="/redoc"
35
76
  )
36
77
 
37
- # Configure CORS
38
- app.add_middleware(
39
- CORSMiddleware,
40
- allow_origins=["*"], # Configure appropriately for production
41
- allow_credentials=True,
42
- allow_methods=["*"],
43
- allow_headers=["*"],
44
- )
78
+ # Setup comprehensive security middleware
79
+ # This includes CORS, rate limiting, security headers, request validation
80
+ setup_security_middleware(app)
45
81
 
46
82
  # Add custom middleware
47
83
  app.add_middleware(RequestLoggerMiddleware)
@@ -64,10 +100,34 @@ def create_app(config: Dict[str, Any] = None) -> FastAPI:
64
100
  # MAIN UNIFIED API - Single endpoint for all AI services
65
101
  app.include_router(unified.router, prefix="/api/v1", tags=["unified-api"])
66
102
 
67
- # Legacy specific endpoints (kept for backward compatibility)
68
- app.include_router(ui_analysis.router, prefix="/ui-analysis", tags=["ui-analysis"])
69
- app.include_router(vision.router, prefix="/vision", tags=["vision"])
70
- app.include_router(llm.router, prefix="/llm", tags=["llm"])
103
+ # DEPLOYMENTS API - Model deployment management
104
+ app.include_router(deployments.router, prefix="/api/v1/deployments", tags=["deployments"])
105
+
106
+ # LOGS API - Log management and streaming
107
+ app.include_router(logs.router, prefix="/api/v1/logs", tags=["logs"])
108
+
109
+ # ANALYTICS API - Usage analytics and reporting
110
+ app.include_router(analytics.router, prefix="/api/v1/analytics", tags=["analytics"])
111
+
112
+ # SETTINGS API - Configuration and API key management
113
+ app.include_router(settings.router, prefix="/api/v1/settings", tags=["settings"])
114
+
115
+ # EVALUATIONS API - Model evaluation and benchmarking
116
+ app.include_router(evaluations.router, prefix="/api/v1/evaluations", tags=["evaluations"])
117
+
118
+ # Mount static files
119
+ static_path = os.path.join(os.path.dirname(__file__), "../static")
120
+ if os.path.exists(static_path):
121
+ app.mount("/static", StaticFiles(directory=static_path), name="static")
122
+
123
+ # Serve management dashboard at /admin
124
+ @app.get("/admin")
125
+ async def admin_dashboard():
126
+ from fastapi.responses import FileResponse
127
+ index_path = os.path.join(static_path, "index.html")
128
+ if os.path.exists(index_path):
129
+ return FileResponse(index_path)
130
+ return {"error": "Management dashboard not found"}
71
131
 
72
132
  # Root endpoint
73
133
  @app.get("/")
@@ -76,9 +136,21 @@ def create_app(config: Dict[str, Any] = None) -> FastAPI:
76
136
  "service": "isa-model-serving",
77
137
  "version": "1.0.0",
78
138
  "status": "running",
79
- "timestamp": time.time()
139
+ "timestamp": time.time(),
140
+ "admin_url": "/admin"
80
141
  }
81
142
 
143
+ # Add startup event handler
144
+ @app.on_event("startup")
145
+ async def startup_event():
146
+ logger.info("🚀 Starting application startup initialization...")
147
+ try:
148
+ await run_startup_initialization()
149
+ logger.info("✅ Application startup completed successfully")
150
+ except Exception as e:
151
+ logger.error(f"❌ Application startup failed: {e}")
152
+ # Don't raise - let the app start anyway
153
+
82
154
  return app
83
155
 
84
156
  # Create default app instance