isa-model 0.3.7__py3-none-any.whl → 0.3.8__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 CHANGED
@@ -138,6 +138,7 @@ class ISAModelClient:
138
138
  model_hint: Optional[str] = None,
139
139
  provider_hint: Optional[str] = None,
140
140
  stream: bool = False,
141
+ tools: Optional[List[Any]] = None,
141
142
  **kwargs
142
143
  ) -> Union[Dict[str, Any], object]:
143
144
  """
@@ -150,6 +151,7 @@ class ISAModelClient:
150
151
  model_hint: Optional model preference
151
152
  provider_hint: Optional provider preference
152
153
  stream: Enable streaming for text services (returns AsyncGenerator)
154
+ tools: Optional list of tools for function calling (only for text services)
153
155
  **kwargs: Additional task-specific parameters
154
156
 
155
157
  Returns:
@@ -174,6 +176,13 @@ class ISAModelClient:
174
176
  async for token in await client.invoke("Hello", "chat", "text", stream=True):
175
177
  print(token, end="", flush=True)
176
178
 
179
+ # Text with tools
180
+ await client.invoke("What's 5+3?", "chat", "text", tools=[calculator_function])
181
+
182
+ # Streaming with tools
183
+ async for token in await client.invoke("What's 5+3?", "chat", "text", stream=True, tools=[calculator_function]):
184
+ print(token, end="")
185
+
177
186
  # Image generation
178
187
  await client.invoke("A beautiful sunset", "generate_image", "image")
179
188
 
@@ -193,6 +202,7 @@ class ISAModelClient:
193
202
  service_type=service_type,
194
203
  model_hint=model_hint,
195
204
  provider_hint=provider_hint,
205
+ tools=tools,
196
206
  **kwargs
197
207
  )
198
208
  else:
@@ -202,6 +212,7 @@ class ISAModelClient:
202
212
  service_type=service_type,
203
213
  model_hint=model_hint,
204
214
  provider_hint=provider_hint,
215
+ tools=tools,
205
216
  **kwargs
206
217
  )
207
218
 
@@ -213,6 +224,7 @@ class ISAModelClient:
213
224
  service_type=service_type,
214
225
  model_hint=model_hint,
215
226
  provider_hint=provider_hint,
227
+ tools=tools,
216
228
  **kwargs
217
229
  )
218
230
  else:
@@ -222,6 +234,7 @@ class ISAModelClient:
222
234
  service_type=service_type,
223
235
  model_hint=model_hint,
224
236
  provider_hint=provider_hint,
237
+ tools=tools,
225
238
  **kwargs
226
239
  )
227
240
 
@@ -349,7 +362,8 @@ class ISAModelClient:
349
362
  service_type: str,
350
363
  model_name: str,
351
364
  provider: str,
352
- task: str
365
+ task: str,
366
+ tools: Optional[List[Any]] = None
353
367
  ) -> Any:
354
368
  """Get appropriate service instance"""
355
369
 
@@ -357,7 +371,11 @@ class ISAModelClient:
357
371
 
358
372
  # Check cache first
359
373
  if cache_key in self._service_cache:
360
- return self._service_cache[cache_key]
374
+ service = self._service_cache[cache_key]
375
+ # If tools are needed, bind them to the service
376
+ if tools and service_type == "text":
377
+ return service.bind_tools(tools)
378
+ return service
361
379
 
362
380
  try:
363
381
  # Route to appropriate AIFactory method
@@ -387,6 +405,11 @@ class ISAModelClient:
387
405
 
388
406
  # Cache the service
389
407
  self._service_cache[cache_key] = service
408
+
409
+ # If tools are needed, bind them to the service
410
+ if tools and service_type == "text":
411
+ return service.bind_tools(tools)
412
+
390
413
  return service
391
414
 
392
415
  except Exception as e:
@@ -616,6 +639,7 @@ class ISAModelClient:
616
639
  service_type: str,
617
640
  model_hint: Optional[str] = None,
618
641
  provider_hint: Optional[str] = None,
642
+ tools: Optional[List[Any]] = None,
619
643
  **kwargs
620
644
  ) -> Dict[str, Any]:
621
645
  """Local invoke using AI Factory (original logic)"""
@@ -634,7 +658,8 @@ class ISAModelClient:
634
658
  service_type=service_type,
635
659
  model_name=selected_model["model_id"],
636
660
  provider=selected_model["provider"],
637
- task=task
661
+ task=task,
662
+ tools=tools
638
663
  )
639
664
 
640
665
  # Step 3: Execute task with unified interface
@@ -823,6 +848,7 @@ class ISAModelClient:
823
848
  service_type: str,
824
849
  model_hint: Optional[str] = None,
825
850
  provider_hint: Optional[str] = None,
851
+ tools: Optional[List[Any]] = None,
826
852
  **kwargs
827
853
  ):
828
854
  """Local streaming using AI Factory"""
@@ -840,7 +866,8 @@ class ISAModelClient:
840
866
  service_type=service_type,
841
867
  model_name=selected_model["model_id"],
842
868
  provider=selected_model["provider"],
843
- task=task
869
+ task=task,
870
+ tools=tools
844
871
  )
845
872
 
846
873
  # Step 3: Yield tokens from the stream
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: isa_model
3
- Version: 0.3.7
3
+ Version: 0.3.8
4
4
  Summary: Unified AI model serving framework
5
5
  Author: isA_Model Contributors
6
6
  Classifier: Development Status :: 3 - Alpha
@@ -1,5 +1,5 @@
1
1
  isa_model/__init__.py,sha256=bAbHdrDVQ-mySC_GJtgfLNI8KPcs2LfReBkIOOtpaQQ,867
2
- isa_model/client.py,sha256=ly4614_LIz5Csg1qG7M-eXtN8VR36ClsMWqsgz111BE,34285
2
+ isa_model/client.py,sha256=oo2WcxElcD9WMtw6STj3vS9KwjI-DvS_ldqC1X-HRBs,35456
3
3
  isa_model/core/config.py,sha256=h9GVTEEMlaJYSCDd0W9q1KtaWTV5V5TawMsKtGuphds,15686
4
4
  isa_model/core/pricing_manager.py,sha256=b7HcZsBQ8ZSCzMepOhqN-J9kU43vhTxX5NabQS0aM70,17125
5
5
  isa_model/core/types.py,sha256=XLUs442WGNc8E0gF2M-nb6dutD_s-XCfpr2BfGBCA2M,8445
@@ -50,16 +50,6 @@ isa_model/inference/__init__.py,sha256=usfuQJ4zYY2RRtHkE-V6LuJ5aN7WJogtPUj9Qmy4W
50
50
  isa_model/inference/ai_factory.py,sha256=oGtRd4wp6IZOTyI3GVKBNN4AtlnrLS7yFZuq2wvkaUg,19784
51
51
  isa_model/inference/base.py,sha256=qwOddnSGI0GUdD6qIdGBPQpkW7UjU3Y-zaZvu70B4WA,1278
52
52
  isa_model/inference/adapter/unified_api.py,sha256=67_Ok8W20m6Otf6r9WyOEVpnxondP4UAxOASk9ozDk4,8668
53
- isa_model/inference/providers/__init__.py,sha256=a83q-LMFv8u47wf0XtxvqOw_mlVgA_90wtuwy02qdDE,581
54
- isa_model/inference/providers/base_provider.py,sha256=PT-YnGwBu-Jn_4T3iAphkAJw_mYmKVLjUID62vf2_Ow,2711
55
- isa_model/inference/providers/ml_provider.py,sha256=4oGGF7lVWQ91Qh3h7olyPFoACLxCROaMxUZlDiZrRL4,1661
56
- isa_model/inference/providers/modal_provider.py,sha256=klRYXECD5TJicodHIElsGNGMAsAWRFhvn4yfCRcqdVs,3654
57
- isa_model/inference/providers/model_cache_manager.py,sha256=dLRpx7OJweQ5LcSAkU7D0DQRfLtIhG6nGvg4W_gau80,15315
58
- isa_model/inference/providers/ollama_provider.py,sha256=IfM9XhdzfE1faguzS2-4GfhK30v5kDPecD3l4z2eB1w,3620
59
- isa_model/inference/providers/openai_provider.py,sha256=tB8FMsMivlRx0cfPJ0Yrxh1DCvuXyyjNFXrO4lMkkhA,5366
60
- isa_model/inference/providers/replicate_provider.py,sha256=0oi_BglIE6-HYgzLau9ifP8OdpAMO-QkwYk0OXRUzPk,4490
61
- isa_model/inference/providers/triton_provider.py,sha256=GKlth7cTOx6ERbsXXJ0gDNby3kVGQNULBDt098BXBSU,15258
62
- isa_model/inference/providers/yyds_provider.py,sha256=KbDsopShs11_G9oX3b2i2NgHIqkZV7HYWe9K9uZLccc,4284
63
53
  isa_model/inference/services/__init__.py,sha256=yfLz0YGl8ixk6LfTRL6cRTvZMb9F_Pv1QRgGyNc9xYM,386
64
54
  isa_model/inference/services/base_service.py,sha256=fVaSx0CogHK71UEsNJeSyM8mhqmq5_9ePbbSZVi3Al8,5085
65
55
  isa_model/inference/services/audio/base_stt_service.py,sha256=sfzAfreFdvEOBHtphoTrQSjb-gCoCOW4WCj6iIe51oU,5804
@@ -142,7 +132,7 @@ isa_model/training/core/config.py,sha256=oqgKpBvtzrN6jwLIQYQ2707lH6nmjrktRiSxp9i
142
132
  isa_model/training/core/dataset.py,sha256=XCFsnf0NUMU1dJpdvo_CAMyvXB-9_RCUEiy8TU50e20,7802
143
133
  isa_model/training/core/trainer.py,sha256=h5TjqjdFr0Fsv5y4-0siy1KmOlqLfliVaUXybvuoeXU,26932
144
134
  isa_model/training/core/utils.py,sha256=Nik0M2ssfNbWqP6fKO0Kfyhzr_H6Q19ioxB-qCYbn5E,8387
145
- isa_model-0.3.7.dist-info/METADATA,sha256=yjnMzsQji2XQeqdlohiHFdWkXahAuXr9aQJOd6tOnQ0,12326
146
- isa_model-0.3.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
147
- isa_model-0.3.7.dist-info/top_level.txt,sha256=eHSy_Xb3kNkh2kK11mi1mZh0Wz91AQ5b8k2KFYO-rE8,10
148
- isa_model-0.3.7.dist-info/RECORD,,
135
+ isa_model-0.3.8.dist-info/METADATA,sha256=rQ6RLtoPX1xoT2BFeRQZTx9gRSeCjRxuTbH3xseKbdE,12326
136
+ isa_model-0.3.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
137
+ isa_model-0.3.8.dist-info/top_level.txt,sha256=eHSy_Xb3kNkh2kK11mi1mZh0Wz91AQ5b8k2KFYO-rE8,10
138
+ isa_model-0.3.8.dist-info/RECORD,,
@@ -1,19 +0,0 @@
1
- """
2
- Providers - Components for integrating with different model providers
3
-
4
- File: isa_model/inference/providers/__init__.py
5
- This module contains provider implementations for different AI model backends.
6
- """
7
-
8
- from .base_provider import BaseProvider
9
-
10
- __all__ = [
11
- "BaseProvider",
12
- ]
13
-
14
- # Provider implementations can be imported individually as needed
15
- # from .triton_provider import TritonProvider
16
- # from .ollama_provider import OllamaProvider
17
- # from .yyds_provider import YYDSProvider
18
- # from .openai_provider import OpenAIProvider
19
- # from .replicate_provider import ReplicateProvider
@@ -1,77 +0,0 @@
1
- from abc import ABC, abstractmethod
2
- from typing import Dict, List, Any, Optional
3
- import os
4
- import logging
5
- from pathlib import Path
6
- import dotenv
7
-
8
- from isa_model.inference.base import ModelType, Capability
9
-
10
- logger = logging.getLogger(__name__)
11
-
12
- class BaseProvider(ABC):
13
- """Base class for all AI providers - handles API key management"""
14
-
15
- def __init__(self, config: Optional[Dict[str, Any]] = None):
16
- self.config = config or {}
17
- self._load_environment_config()
18
- self._validate_config()
19
-
20
- def _load_environment_config(self):
21
- """Load configuration from environment variables"""
22
- # Load .env file if it exists
23
- project_root = Path(__file__).parent.parent.parent.parent
24
- env_path = project_root / ".env"
25
-
26
- if env_path.exists():
27
- dotenv.load_dotenv(env_path)
28
-
29
- # Subclasses should override this to load provider-specific env vars
30
- self._load_provider_env_vars()
31
-
32
- @abstractmethod
33
- def _load_provider_env_vars(self):
34
- """Load provider-specific environment variables"""
35
- pass
36
-
37
- def _validate_config(self):
38
- """Validate that required configuration is present"""
39
- # Subclasses should override this to validate provider-specific config
40
- pass
41
-
42
- def get_api_key(self) -> Optional[str]:
43
- """Get the API key for this provider"""
44
- return self.config.get("api_key")
45
-
46
- def has_valid_credentials(self) -> bool:
47
- """Check if provider has valid credentials"""
48
- return bool(self.get_api_key())
49
-
50
- @abstractmethod
51
- def get_capabilities(self) -> Dict[ModelType, List[Capability]]:
52
- """Get provider capabilities by model type"""
53
- pass
54
-
55
- @abstractmethod
56
- def get_models(self, model_type: ModelType) -> List[str]:
57
- """Get available models for given type"""
58
- pass
59
-
60
- def get_config(self) -> Dict[str, Any]:
61
- """Get provider configuration (without sensitive data)"""
62
- # Return a copy without sensitive information
63
- config_copy = self.config.copy()
64
- if "api_key" in config_copy:
65
- config_copy["api_key"] = "***" if config_copy["api_key"] else ""
66
- if "api_token" in config_copy:
67
- config_copy["api_token"] = "***" if config_copy["api_token"] else ""
68
- return config_copy
69
-
70
- def get_full_config(self) -> Dict[str, Any]:
71
- """Get full provider configuration (including sensitive data) - for internal use only"""
72
- return self.config.copy()
73
-
74
- @abstractmethod
75
- def is_reasoning_model(self, model_name: str) -> bool:
76
- """Check if the model is optimized for reasoning tasks"""
77
- pass
@@ -1,50 +0,0 @@
1
- from isa_model.inference.providers.base_provider import BaseProvider
2
- from isa_model.inference.base import ModelType, Capability
3
- from typing import Dict, List, Any
4
- import logging
5
-
6
- logger = logging.getLogger(__name__)
7
-
8
- class MLProvider(BaseProvider):
9
- """Provider for traditional ML models"""
10
-
11
- def __init__(self, config=None):
12
- default_config = {
13
- "model_directory": "./models/ml",
14
- "cache_models": True,
15
- "max_cache_size": 5
16
- }
17
-
18
- merged_config = {**default_config, **(config or {})}
19
- super().__init__(config=merged_config)
20
- self.name = "ml"
21
-
22
- logger.info(f"Initialized MLProvider with model directory: {self.config['model_directory']}")
23
-
24
- def get_capabilities(self) -> Dict[ModelType, List[Capability]]:
25
- """Get provider capabilities"""
26
- return {
27
- ModelType.LLM: [], # ML models are not LLMs
28
- ModelType.EMBEDDING: [],
29
- ModelType.VISION: [],
30
- "ML": [ # Custom model type for traditional ML
31
- "CLASSIFICATION",
32
- "REGRESSION",
33
- "CLUSTERING",
34
- "FEATURE_EXTRACTION"
35
- ]
36
- }
37
-
38
- def get_models(self, model_type: str = "ML") -> List[str]:
39
- """Get available ML models"""
40
- # In practice, this would scan the model directory
41
- return [
42
- "fraud_detection_rf",
43
- "customer_churn_xgb",
44
- "price_prediction_lr",
45
- "recommendation_kmeans"
46
- ]
47
-
48
- def get_config(self) -> Dict[str, Any]:
49
- """Get provider configuration"""
50
- return self.config
@@ -1,109 +0,0 @@
1
- """
2
- Modal Provider
3
-
4
- Provider for ISA self-hosted Modal services
5
- No API keys needed since we deploy our own services
6
- """
7
-
8
- import os
9
- import logging
10
- from typing import Dict, Any, Optional, List
11
- from .base_provider import BaseProvider
12
- from isa_model.inference.base import ModelType, Capability
13
-
14
- logger = logging.getLogger(__name__)
15
-
16
- class ModalProvider(BaseProvider):
17
- """Provider for ISA Modal services"""
18
-
19
- def __init__(self, config: Optional[Dict[str, Any]] = None):
20
- super().__init__(config)
21
- self.name = "modal"
22
- self.base_url = "https://modal.com" # Not used directly
23
-
24
- def _load_provider_env_vars(self):
25
- """Load Modal-specific environment variables"""
26
- # Modal doesn't need API keys for deployed services
27
- # But we can load Modal token if available
28
- modal_token = os.getenv("MODAL_TOKEN_ID") or os.getenv("MODAL_TOKEN_SECRET")
29
- if modal_token:
30
- self.config["modal_token"] = modal_token
31
-
32
- # Set default config
33
- if "timeout" not in self.config:
34
- self.config["timeout"] = 300
35
- if "deployment_region" not in self.config:
36
- self.config["deployment_region"] = "us-east-1"
37
- if "gpu_type" not in self.config:
38
- self.config["gpu_type"] = "T4"
39
-
40
- def get_api_key(self) -> str:
41
- """Modal services don't need API keys for deployed apps"""
42
- return "modal-deployed-service" # Placeholder
43
-
44
- def get_base_url(self) -> str:
45
- """Get base URL for Modal services"""
46
- return self.base_url
47
-
48
- def validate_credentials(self) -> bool:
49
- """
50
- Validate Modal credentials
51
- For deployed services, we assume they're accessible
52
- """
53
- try:
54
- # Check if Modal is available
55
- import modal
56
- return True
57
- except ImportError:
58
- logger.warning("Modal package not available")
59
- return False
60
-
61
- def get_capabilities(self) -> Dict[ModelType, List[Capability]]:
62
- """Get Modal provider capabilities"""
63
- return {
64
- ModelType.VISION: [
65
- Capability.OBJECT_DETECTION,
66
- Capability.IMAGE_ANALYSIS,
67
- Capability.UI_DETECTION,
68
- Capability.OCR,
69
- Capability.DOCUMENT_ANALYSIS
70
- ]
71
- }
72
-
73
- def get_models(self, model_type: ModelType) -> List[str]:
74
- """Get available models for given type"""
75
- if model_type == ModelType.VISION:
76
- return [
77
- "omniparser-v2.0",
78
- "table-transformer-detection",
79
- "table-transformer-structure-v1.1",
80
- "paddleocr-3.0",
81
- "yolov8"
82
- ]
83
- return []
84
-
85
- def is_reasoning_model(self, model_name: str) -> bool:
86
- """Check if the model is optimized for reasoning tasks"""
87
- # Vision models are not reasoning models
88
- return False
89
-
90
- def get_default_config(self) -> Dict[str, Any]:
91
- """Get default configuration for Modal services"""
92
- return {
93
- "timeout": 300, # 5 minutes
94
- "max_retries": 3,
95
- "deployment_region": "us-east-1",
96
- "gpu_type": "T4"
97
- }
98
-
99
- def get_billing_info(self) -> Dict[str, Any]:
100
- """Get billing information for Modal services"""
101
- return {
102
- "provider": "modal",
103
- "billing_model": "compute_usage",
104
- "cost_per_hour": {
105
- "T4": 0.60,
106
- "A100": 4.00
107
- },
108
- "note": "Costs depend on actual usage time, scales to zero when not in use"
109
- }