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
@@ -2,7 +2,7 @@
2
2
  # -*- coding: utf-8 -*-
3
3
 
4
4
  """
5
- Intelligent Model Selector - Simple similarity-based model selection
5
+ Intelligent Model Selector - Embedding-based model selection
6
6
  Uses embedding similarity matching against model descriptions and metadata
7
7
  """
8
8
 
@@ -10,44 +10,28 @@ import logging
10
10
  import asyncio
11
11
  import json
12
12
  from typing import Dict, List, Any, Optional, Tuple
13
- from pathlib import Path
14
- import yaml
15
13
 
16
14
  logger = logging.getLogger(__name__)
17
15
 
18
- try:
19
- import asyncpg
20
- from pgvector.asyncpg import register_vector
21
- PGVECTOR_AVAILABLE = True
22
- except ImportError:
23
- PGVECTOR_AVAILABLE = False
24
- logger.warning("pgvector not available, model selector will use in-memory fallback")
25
-
26
- try:
27
- from supabase import create_client, Client
28
- SUPABASE_AVAILABLE = True
29
- except ImportError:
30
- SUPABASE_AVAILABLE = False
31
- logger.warning("Supabase not available, falling back to SQLite")
16
+ from ..database.supabase_client import get_supabase_client
17
+ from ...inference.ai_factory import AIFactory
32
18
 
33
19
 
34
20
  class IntelligentModelSelector:
35
21
  """
36
- Simple intelligent model selector using embedding similarity
22
+ Intelligent model selector using embedding similarity
37
23
 
38
24
  Features:
39
- - Embeds model descriptions and metadata
40
- - Stores embeddings in pgvector for fast similarity search
41
- - Falls back to in-memory similarity if pgvector unavailable
25
+ - Reads models from database registry
26
+ - Uses unified Supabase client
27
+ - Uses existing embedding service for similarity matching
42
28
  - Has default models for each service type
43
29
  """
44
30
 
45
31
  def __init__(self, config: Optional[Dict[str, Any]] = None):
46
32
  self.config = config or {}
47
- self.db_pool = None
48
33
  self.supabase_client = None
49
34
  self.embedding_service = None
50
- self.model_embeddings: Dict[str, List[float]] = {}
51
35
  self.models_metadata: Dict[str, Dict[str, Any]] = {}
52
36
 
53
37
  # Default models for each service type
@@ -55,7 +39,7 @@ class IntelligentModelSelector:
55
39
  "vision": {"model_id": "gpt-4.1-mini", "provider": "openai"},
56
40
  "audio": {"model_id": "whisper-1", "provider": "openai"},
57
41
  "text": {"model_id": "gpt-4.1-mini", "provider": "openai"},
58
- "image": {"model_id": "flux-schnell", "provider": "replicate"},
42
+ "image": {"model_id": "black-forest-labs/flux-schnell", "provider": "replicate"},
59
43
  "embedding": {"model_id": "text-embedding-3-small", "provider": "openai"},
60
44
  "omni": {"model_id": "gpt-4.1", "provider": "openai"}
61
45
  }
@@ -65,17 +49,15 @@ class IntelligentModelSelector:
65
49
  async def initialize(self):
66
50
  """Initialize the model selector"""
67
51
  try:
52
+ # Initialize Supabase client
53
+ self.supabase_client = get_supabase_client()
54
+ logger.info("Supabase client initialized")
55
+
68
56
  # Initialize embedding service
69
57
  await self._init_embedding_service()
70
58
 
71
- # Initialize database - try Supabase first, then PostgreSQL
72
- if SUPABASE_AVAILABLE and self.config.get("supabase"):
73
- await self._init_supabase()
74
- elif PGVECTOR_AVAILABLE:
75
- await self._init_database()
76
-
77
- # Load and embed models
78
- await self._load_models()
59
+ # Load models from database
60
+ await self._load_models_from_database()
79
61
 
80
62
  logger.info("Model selector fully initialized")
81
63
 
@@ -86,199 +68,58 @@ class IntelligentModelSelector:
86
68
  async def _init_embedding_service(self):
87
69
  """Initialize embedding service for text similarity"""
88
70
  try:
89
- from isa_model.inference.ai_factory import AIFactory
90
71
  factory = AIFactory.get_instance()
91
72
  self.embedding_service = factory.get_embed("text-embedding-3-small", "openai")
92
73
  logger.info("Embedding service initialized")
93
74
  except Exception as e:
94
75
  logger.warning(f"Failed to initialize embedding service: {e}")
95
76
 
96
- async def _init_supabase(self):
97
- """Initialize Supabase client for vector search"""
77
+ async def _load_models_from_database(self):
78
+ """Load models from database registry"""
98
79
  try:
99
- supabase_config = self.config.get("supabase", {})
100
- url = supabase_config.get("url")
101
- key = supabase_config.get("key")
102
-
103
- if not url or not key:
104
- # Try environment variables
105
- import os
106
- url = url or os.getenv("SUPABASE_URL")
107
- key = key or os.getenv("SUPABASE_ANON_KEY")
80
+ # Get all models from database
81
+ result = self.supabase_client.table('models').select('*').execute()
82
+ models = result.data
108
83
 
109
- if not url or not key:
110
- raise ValueError("Supabase URL and key are required")
111
-
112
- self.supabase_client = create_client(url, key)
113
- logger.info("Supabase client initialized successfully")
114
-
115
- except Exception as e:
116
- logger.warning(f"Supabase initialization failed: {e}, using in-memory fallback")
117
- self.supabase_client = None
118
-
119
- async def _init_database(self):
120
- """Initialize pgvector database connection"""
121
- try:
122
- # Get database configuration
123
- db_config = self.config.get("database", {
124
- "host": "localhost",
125
- "port": 5432,
126
- "database": "isa_model",
127
- "user": "postgres",
128
- "password": "password"
129
- })
130
-
131
- # Create connection pool
132
- self.db_pool = await asyncpg.create_pool(
133
- host=db_config["host"],
134
- port=db_config["port"],
135
- database=db_config["database"],
136
- user=db_config["user"],
137
- password=db_config["password"],
138
- min_size=1,
139
- max_size=5
140
- )
141
-
142
- # Register vector extension
143
- async with self.db_pool.acquire() as conn:
144
- await register_vector(conn)
145
-
146
- # Create models table if not exists
147
- await conn.execute("""
148
- CREATE EXTENSION IF NOT EXISTS vector;
149
-
150
- CREATE TABLE IF NOT EXISTS model_embeddings (
151
- id SERIAL PRIMARY KEY,
152
- model_id VARCHAR(255) UNIQUE NOT NULL,
153
- provider VARCHAR(100) NOT NULL,
154
- model_type VARCHAR(50) NOT NULL,
155
- description TEXT,
156
- metadata JSONB,
157
- embedding vector(1536),
158
- created_at TIMESTAMP DEFAULT NOW(),
159
- updated_at TIMESTAMP DEFAULT NOW()
160
- );
161
-
162
- CREATE INDEX IF NOT EXISTS idx_model_embeddings_similarity
163
- ON model_embeddings USING ivfflat (embedding vector_cosine_ops);
164
- """)
165
-
166
- logger.info("Database initialized successfully")
167
-
168
- except Exception as e:
169
- logger.warning(f"Database initialization failed: {e}, using in-memory fallback")
170
- self.db_pool = None
171
-
172
- async def _load_models(self):
173
- """Load models from YAML configs and create embeddings"""
174
- try:
175
- # Get config directory
176
- config_dir = Path(__file__).parent.parent.parent / "config" / "models"
177
-
178
- if not config_dir.exists():
179
- logger.warning(f"Model config directory not found: {config_dir}")
180
- return
181
-
182
- # Load all YAML files
183
- for yaml_file in config_dir.glob("*.yaml"):
184
- await self._load_models_from_file(yaml_file)
185
-
186
- logger.info(f"Loaded {len(self.models_metadata)} models for similarity matching")
187
-
188
- except Exception as e:
189
- logger.error(f"Failed to load models: {e}")
190
-
191
- async def _load_models_from_file(self, yaml_file: Path):
192
- """Load models from a specific YAML file"""
193
- try:
194
- with open(yaml_file, 'r', encoding='utf-8') as f:
195
- data = yaml.safe_load(f)
196
-
197
- provider = data.get("provider", "unknown")
198
- models = data.get("models", [])
84
+ logger.info(f"Found {len(models)} models in database registry")
199
85
 
86
+ # Process each model
200
87
  for model in models:
201
- await self._process_model(model, provider)
88
+ model_id = model['model_id']
202
89
 
203
- except Exception as e:
204
- logger.error(f"Failed to load models from {yaml_file}: {e}")
205
-
206
- async def _process_model(self, model: Dict[str, Any], provider: str):
207
- """Process a single model and create embeddings"""
208
- try:
209
- model_id = model.get("model_id")
210
- if not model_id:
211
- return
90
+ # Parse metadata if it's a string (from JSONB)
91
+ metadata_raw = model.get('metadata', '{}')
92
+ if isinstance(metadata_raw, str):
93
+ try:
94
+ metadata = json.loads(metadata_raw)
95
+ except json.JSONDecodeError:
96
+ metadata = {}
97
+ else:
98
+ metadata = metadata_raw if isinstance(metadata_raw, dict) else {}
99
+
100
+ # Store model metadata
101
+ self.models_metadata[model_id] = {
102
+ "provider": model['provider'],
103
+ "model_type": model['model_type'],
104
+ "metadata": metadata
105
+ }
212
106
 
213
- # Create searchable text from description and metadata
214
- description = model.get("metadata", {}).get("description", "")
215
- specialized_tasks = model.get("metadata", {}).get("specialized_tasks", [])
216
- capabilities = model.get("capabilities", [])
107
+ # Check embeddings status
108
+ embeddings_result = self.supabase_client.table('model_embeddings').select('model_id').execute()
109
+ existing_embeddings = {row['model_id'] for row in embeddings_result.data}
217
110
 
218
- # Combine all text for embedding
219
- search_text = f"{description} "
220
- search_text += f"Capabilities: {', '.join(capabilities)} "
221
- search_text += f"Tasks: {', '.join(specialized_tasks)}"
111
+ logger.info(f"Found {len(existing_embeddings)} model embeddings")
112
+ logger.info(f"Loaded {len(self.models_metadata)} models for similarity matching")
222
113
 
223
- # Create embedding
224
- if self.embedding_service:
225
- try:
226
- embedding = await self.embedding_service.create_text_embedding(search_text)
227
-
228
- # Store model metadata
229
- self.models_metadata[model_id] = {
230
- "provider": provider,
231
- "model_type": model.get("model_type"),
232
- "capabilities": capabilities,
233
- "metadata": model.get("metadata", {}),
234
- "search_text": search_text
235
- }
236
-
237
- # Store embedding
238
- if self.db_pool:
239
- await self._store_model_embedding(model_id, provider, model, embedding)
240
- else:
241
- self.model_embeddings[model_id] = embedding
242
-
243
- except Exception as e:
244
- logger.warning(f"Failed to create embedding for {model_id}: {e}")
114
+ # Warn if models don't have embeddings
115
+ missing_embeddings = set(self.models_metadata.keys()) - existing_embeddings
116
+ if missing_embeddings:
117
+ logger.warning(f"Models without embeddings: {list(missing_embeddings)}")
118
+ logger.warning("Embeddings are generated during startup. Consider restarting the service.")
245
119
 
246
120
  except Exception as e:
247
- logger.error(f"Failed to process model {model.get('model_id', 'unknown')}: {e}")
121
+ logger.error(f"Failed to load models from database: {e}")
248
122
 
249
- async def _store_model_embedding(
250
- self,
251
- model_id: str,
252
- provider: str,
253
- model: Dict[str, Any],
254
- embedding: List[float]
255
- ):
256
- """Store model embedding in database"""
257
- try:
258
- async with self.db_pool.acquire() as conn:
259
- await conn.execute("""
260
- INSERT INTO model_embeddings
261
- (model_id, provider, model_type, description, metadata, embedding)
262
- VALUES ($1, $2, $3, $4, $5, $6)
263
- ON CONFLICT (model_id)
264
- DO UPDATE SET
265
- provider = $2,
266
- model_type = $3,
267
- description = $4,
268
- metadata = $5,
269
- embedding = $6,
270
- updated_at = NOW()
271
- """,
272
- model_id,
273
- provider,
274
- model.get("model_type"),
275
- model.get("metadata", {}).get("description", ""),
276
- json.dumps(model.get("metadata", {})),
277
- embedding
278
- )
279
-
280
- except Exception as e:
281
- logger.error(f"Failed to store embedding for {model_id}: {e}")
282
123
 
283
124
  async def select_model(
284
125
  self,
@@ -304,13 +145,8 @@ class IntelligentModelSelector:
304
145
 
305
146
  request_embedding = await self.embedding_service.create_text_embedding(request)
306
147
 
307
- # Find similar models
308
- if self.supabase_client:
309
- candidates = await self._find_similar_models_supabase(request_embedding, service_type)
310
- elif self.db_pool:
311
- candidates = await self._find_similar_models_db(request_embedding, service_type)
312
- else:
313
- candidates = await self._find_similar_models_memory(request_embedding, service_type)
148
+ # Find similar models using Supabase
149
+ candidates = await self._find_similar_models_supabase(request_embedding, service_type)
314
150
 
315
151
  if not candidates:
316
152
  return self._get_default_selection(service_type, "No suitable models found")
@@ -338,127 +174,60 @@ class IntelligentModelSelector:
338
174
  request_embedding: List[float],
339
175
  service_type: str
340
176
  ) -> List[Dict[str, Any]]:
341
- """Find similar models using Supabase RPC function"""
177
+ """Find similar models using Supabase and embedding service similarity"""
342
178
  try:
343
- # Use the RPC function we created in SQL
344
- result = self.supabase_client.rpc(
345
- 'search_similar_models',
346
- {
347
- 'query_embedding': request_embedding,
348
- 'similarity_threshold': 0.3, # Minimum similarity threshold
349
- 'match_count': 10,
350
- 'filter_model_type': service_type
351
- }
352
- ).execute()
353
-
354
- candidates = []
355
- for row in result.data:
356
- candidates.append({
357
- "model_id": row["model_id"],
358
- "provider": row["provider"],
359
- "model_type": row["model_type"],
360
- "similarity": float(row["similarity"]),
361
- "description": row.get("description", "")
362
- })
179
+ # Get all model embeddings from database
180
+ embeddings_result = self.supabase_client.table('model_embeddings').select('*').execute()
181
+ model_embeddings = embeddings_result.data
363
182
 
364
- return candidates
183
+ if not model_embeddings:
184
+ logger.warning("No model embeddings found in database")
185
+ return []
365
186
 
366
- except Exception as e:
367
- logger.error(f"Supabase similarity search failed: {e}")
368
- return []
369
-
370
- async def _find_similar_models_db(
371
- self,
372
- request_embedding: List[float],
373
- service_type: str
374
- ) -> List[Dict[str, Any]]:
375
- """Find similar models using database"""
376
- try:
377
- async with self.db_pool.acquire() as conn:
378
- # Query for similar models
379
- rows = await conn.fetch("""
380
- SELECT
381
- model_id,
382
- provider,
383
- model_type,
384
- description,
385
- metadata,
386
- 1 - (embedding <=> $1) as similarity
387
- FROM model_embeddings
388
- WHERE model_type = $2 OR model_type = 'omni'
389
- ORDER BY embedding <=> $1
390
- LIMIT 10
391
- """, request_embedding, service_type)
392
-
393
- candidates = []
394
- for row in rows:
395
- candidates.append({
396
- "model_id": row["model_id"],
397
- "provider": row["provider"],
398
- "model_type": row["model_type"],
399
- "similarity": float(row["similarity"]),
400
- "description": row["description"]
401
- })
402
-
403
- return candidates
404
-
405
- except Exception as e:
406
- logger.error(f"Database similarity search failed: {e}")
407
- return []
408
-
409
- async def _find_similar_models_memory(
410
- self,
411
- request_embedding: List[float],
412
- service_type: str
413
- ) -> List[Dict[str, Any]]:
414
- """Find similar models using in-memory search"""
415
- try:
187
+ # Calculate similarity for each model
416
188
  candidates = []
417
-
418
- for model_id, embedding in self.model_embeddings.items():
419
- metadata = self.models_metadata.get(model_id, {})
420
- model_type = metadata.get("model_type")
189
+ for model_embed in model_embeddings:
190
+ model_id = model_embed['model_id']
191
+ model_embedding = model_embed['embedding']
192
+
193
+ # Get model metadata
194
+ model_metadata = self.models_metadata.get(model_id, {})
195
+ model_type = model_metadata.get('model_type')
421
196
 
422
197
  # Filter by service type (including omni models)
423
- if model_type not in [service_type, "omni"]:
198
+ if model_type not in [service_type, 'omni']:
424
199
  continue
425
200
 
426
- # Calculate cosine similarity
427
- similarity = self._cosine_similarity(request_embedding, embedding)
428
-
429
- candidates.append({
430
- "model_id": model_id,
431
- "provider": metadata.get("provider"),
432
- "model_type": model_type,
433
- "similarity": similarity,
434
- "description": metadata.get("metadata", {}).get("description", "")
435
- })
201
+ # Calculate similarity using embedding service
202
+ try:
203
+ similarity_result = await self.embedding_service.invoke(
204
+ input_data="", # Not used for similarity task
205
+ task="similarity",
206
+ embedding1=request_embedding,
207
+ embedding2=model_embedding
208
+ )
209
+ similarity = similarity_result['similarity']
210
+
211
+ candidates.append({
212
+ "model_id": model_id,
213
+ "provider": model_embed['provider'],
214
+ "model_type": model_type,
215
+ "similarity": similarity,
216
+ "description": model_embed.get('description', '')
217
+ })
218
+
219
+ except Exception as e:
220
+ logger.warning(f"Failed to calculate similarity for {model_id}: {e}")
221
+ continue
436
222
 
437
223
  # Sort by similarity score
438
224
  candidates.sort(key=lambda x: x["similarity"], reverse=True)
439
- return candidates[:10]
225
+ return candidates[:10] # Return top 10
440
226
 
441
227
  except Exception as e:
442
- logger.error(f"Memory similarity search failed: {e}")
228
+ logger.error(f"Supabase similarity search failed: {e}")
443
229
  return []
444
230
 
445
- def _cosine_similarity(self, vec1: List[float], vec2: List[float]) -> float:
446
- """Calculate cosine similarity between two vectors"""
447
- try:
448
- import math
449
-
450
- dot_product = sum(a * b for a, b in zip(vec1, vec2))
451
- norm1 = math.sqrt(sum(a * a for a in vec1))
452
- norm2 = math.sqrt(sum(b * b for b in vec2))
453
-
454
- if norm1 * norm2 == 0:
455
- return 0.0
456
-
457
- return dot_product / (norm1 * norm2)
458
-
459
- except Exception:
460
- return 0.0
461
-
462
231
  def _get_default_selection(self, service_type: str, reason: str) -> Dict[str, Any]:
463
232
  """Get default model selection"""
464
233
  default = self.default_models.get(service_type, self.default_models["vision"])
@@ -474,50 +243,15 @@ class IntelligentModelSelector:
474
243
  async def get_available_models(self, service_type: Optional[str] = None) -> List[Dict[str, Any]]:
475
244
  """Get list of available models"""
476
245
  try:
477
- if self.supabase_client:
478
- # Query Supabase
479
- query = self.supabase_client.table("model_embedding").select("model_id, provider, model_type, description, metadata")
480
-
481
- if service_type:
482
- query = query.or_(f"model_type.eq.{service_type},model_type.eq.omni")
483
-
484
- result = query.order("model_id").execute()
485
- return result.data
486
-
487
- elif self.db_pool:
488
- async with self.db_pool.acquire() as conn:
489
- if service_type:
490
- rows = await conn.fetch("""
491
- SELECT model_id, provider, model_type, description, metadata
492
- FROM model_embeddings
493
- WHERE model_type = $1 OR model_type = 'omni'
494
- ORDER BY model_id
495
- """, service_type)
496
- else:
497
- rows = await conn.fetch("""
498
- SELECT model_id, provider, model_type, description, metadata
499
- FROM model_embeddings
500
- ORDER BY model_type, model_id
501
- """)
502
-
503
- return [dict(row) for row in rows]
246
+ if service_type:
247
+ # Filter by service type
248
+ query = self.supabase_client.table('models').select('*').or_(f'model_type.eq.{service_type},model_type.eq.omni')
504
249
  else:
505
- # In-memory fallback
506
- models = []
507
- for model_id, metadata in self.models_metadata.items():
508
- model_type = metadata.get("model_type")
509
- if service_type and model_type not in [service_type, "omni"]:
510
- continue
511
-
512
- models.append({
513
- "model_id": model_id,
514
- "provider": metadata.get("provider"),
515
- "model_type": model_type,
516
- "description": metadata.get("metadata", {}).get("description", ""),
517
- "metadata": metadata.get("metadata", {})
518
- })
519
-
520
- return models
250
+ # Get all models
251
+ query = self.supabase_client.table('models').select('*')
252
+
253
+ result = query.order('model_id').execute()
254
+ return result.data
521
255
 
522
256
  except Exception as e:
523
257
  logger.error(f"Failed to get available models: {e}")
@@ -525,12 +259,9 @@ class IntelligentModelSelector:
525
259
 
526
260
  async def close(self):
527
261
  """Clean up resources"""
528
- if self.db_pool:
529
- await self.db_pool.close()
530
- logger.info("Database connection closed")
531
- if self.supabase_client:
532
- # Supabase client doesn't need explicit closing
533
- logger.info("Supabase client cleaned up")
262
+ if self.embedding_service:
263
+ await self.embedding_service.close()
264
+ logger.info("Embedding service closed")
534
265
 
535
266
 
536
267
  # Singleton instance
@@ -21,7 +21,7 @@ try:
21
21
  except ImportError:
22
22
  HF_HUB_AVAILABLE = False
23
23
 
24
- from ..model_storage import ModelStorage
24
+ from ..models.model_storage import ModelStorage
25
25
 
26
26
  logger = logging.getLogger(__name__)
27
27
 
isa_model/core/types.py CHANGED
@@ -33,6 +33,10 @@ class ModelCapability(str, Enum):
33
33
  IMAGE_GENERATION = "image_generation"
34
34
  IMAGE_ANALYSIS = "image_analysis"
35
35
  AUDIO_TRANSCRIPTION = "audio_transcription"
36
+ AUDIO_REALTIME = "audio_realtime"
37
+ SPEECH_TO_TEXT = "speech_to_text"
38
+ TEXT_TO_SPEECH = "text_to_speech"
39
+ CONVERSATION = "conversation"
36
40
  IMAGE_UNDERSTANDING = "image_understanding"
37
41
  UI_DETECTION = "ui_detection"
38
42
  OCR = "ocr"
@@ -56,6 +60,9 @@ class ServiceType(str, Enum):
56
60
  EMBEDDING = "embedding"
57
61
  VISION = "vision"
58
62
  AUDIO = "audio"
63
+ AUDIO_STT = "audio_stt"
64
+ AUDIO_TTS = "audio_tts"
65
+ AUDIO_REALTIME = "audio_realtime"
59
66
  IMAGE_GEN = "image_gen"
60
67
 
61
68
  class ServiceStatus(str, Enum):