isa-model 0.0.2__py3-none-any.whl → 0.3.1__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 (93) hide show
  1. isa_model/__init__.py +1 -1
  2. isa_model/core/model_manager.py +69 -4
  3. isa_model/core/model_registry.py +273 -46
  4. isa_model/core/storage/hf_storage.py +419 -0
  5. isa_model/deployment/__init__.py +52 -0
  6. isa_model/deployment/core/__init__.py +34 -0
  7. isa_model/deployment/core/deployment_config.py +356 -0
  8. isa_model/deployment/core/deployment_manager.py +549 -0
  9. isa_model/deployment/core/isa_deployment_service.py +401 -0
  10. isa_model/eval/factory.py +381 -140
  11. isa_model/inference/ai_factory.py +427 -236
  12. isa_model/inference/billing_tracker.py +406 -0
  13. isa_model/inference/providers/base_provider.py +51 -4
  14. isa_model/inference/providers/ml_provider.py +50 -0
  15. isa_model/inference/providers/ollama_provider.py +37 -18
  16. isa_model/inference/providers/openai_provider.py +65 -36
  17. isa_model/inference/providers/replicate_provider.py +42 -30
  18. isa_model/inference/services/audio/base_stt_service.py +21 -2
  19. isa_model/inference/services/audio/openai_realtime_service.py +353 -0
  20. isa_model/inference/services/audio/openai_stt_service.py +252 -0
  21. isa_model/inference/services/audio/openai_tts_service.py +149 -9
  22. isa_model/inference/services/audio/replicate_tts_service.py +239 -0
  23. isa_model/inference/services/base_service.py +36 -1
  24. isa_model/inference/services/embedding/base_embed_service.py +112 -0
  25. isa_model/inference/services/embedding/ollama_embed_service.py +28 -2
  26. isa_model/inference/services/embedding/openai_embed_service.py +223 -0
  27. isa_model/inference/services/llm/__init__.py +2 -0
  28. isa_model/inference/services/llm/base_llm_service.py +158 -86
  29. isa_model/inference/services/llm/llm_adapter.py +414 -0
  30. isa_model/inference/services/llm/ollama_llm_service.py +252 -63
  31. isa_model/inference/services/llm/openai_llm_service.py +231 -93
  32. isa_model/inference/services/llm/triton_llm_service.py +481 -0
  33. isa_model/inference/services/ml/base_ml_service.py +78 -0
  34. isa_model/inference/services/ml/sklearn_ml_service.py +140 -0
  35. isa_model/inference/services/vision/__init__.py +3 -3
  36. isa_model/inference/services/vision/base_image_gen_service.py +161 -0
  37. isa_model/inference/services/vision/base_vision_service.py +177 -0
  38. isa_model/inference/services/vision/helpers/image_utils.py +4 -3
  39. isa_model/inference/services/vision/ollama_vision_service.py +151 -17
  40. isa_model/inference/services/vision/openai_vision_service.py +275 -41
  41. isa_model/inference/services/vision/replicate_image_gen_service.py +278 -118
  42. isa_model/training/__init__.py +62 -32
  43. isa_model/training/cloud/__init__.py +22 -0
  44. isa_model/training/cloud/job_orchestrator.py +402 -0
  45. isa_model/training/cloud/runpod_trainer.py +454 -0
  46. isa_model/training/cloud/storage_manager.py +482 -0
  47. isa_model/training/core/__init__.py +23 -0
  48. isa_model/training/core/config.py +181 -0
  49. isa_model/training/core/dataset.py +222 -0
  50. isa_model/training/core/trainer.py +720 -0
  51. isa_model/training/core/utils.py +213 -0
  52. isa_model/training/factory.py +229 -198
  53. isa_model-0.3.1.dist-info/METADATA +465 -0
  54. isa_model-0.3.1.dist-info/RECORD +91 -0
  55. isa_model/core/model_router.py +0 -226
  56. isa_model/core/model_version.py +0 -0
  57. isa_model/core/resource_manager.py +0 -202
  58. isa_model/deployment/gpu_fp16_ds8/models/deepseek_r1/1/model.py +0 -120
  59. isa_model/deployment/gpu_fp16_ds8/scripts/download_model.py +0 -18
  60. isa_model/training/engine/llama_factory/__init__.py +0 -39
  61. isa_model/training/engine/llama_factory/config.py +0 -115
  62. isa_model/training/engine/llama_factory/data_adapter.py +0 -284
  63. isa_model/training/engine/llama_factory/examples/__init__.py +0 -6
  64. isa_model/training/engine/llama_factory/examples/finetune_with_tracking.py +0 -185
  65. isa_model/training/engine/llama_factory/examples/rlhf_with_tracking.py +0 -163
  66. isa_model/training/engine/llama_factory/factory.py +0 -331
  67. isa_model/training/engine/llama_factory/rl.py +0 -254
  68. isa_model/training/engine/llama_factory/trainer.py +0 -171
  69. isa_model/training/image_model/configs/create_config.py +0 -37
  70. isa_model/training/image_model/configs/create_flux_config.py +0 -26
  71. isa_model/training/image_model/configs/create_lora_config.py +0 -21
  72. isa_model/training/image_model/prepare_massed_compute.py +0 -97
  73. isa_model/training/image_model/prepare_upload.py +0 -17
  74. isa_model/training/image_model/raw_data/create_captions.py +0 -16
  75. isa_model/training/image_model/raw_data/create_lora_captions.py +0 -20
  76. isa_model/training/image_model/raw_data/pre_processing.py +0 -200
  77. isa_model/training/image_model/train/train.py +0 -42
  78. isa_model/training/image_model/train/train_flux.py +0 -41
  79. isa_model/training/image_model/train/train_lora.py +0 -57
  80. isa_model/training/image_model/train_main.py +0 -25
  81. isa_model-0.0.2.dist-info/METADATA +0 -327
  82. isa_model-0.0.2.dist-info/RECORD +0 -92
  83. isa_model-0.0.2.dist-info/licenses/LICENSE +0 -21
  84. /isa_model/training/{llm_model/annotation → annotation}/annotation_schema.py +0 -0
  85. /isa_model/training/{llm_model/annotation → annotation}/processors/annotation_processor.py +0 -0
  86. /isa_model/training/{llm_model/annotation → annotation}/storage/dataset_manager.py +0 -0
  87. /isa_model/training/{llm_model/annotation → annotation}/storage/dataset_schema.py +0 -0
  88. /isa_model/training/{llm_model/annotation → annotation}/tests/test_annotation_flow.py +0 -0
  89. /isa_model/training/{llm_model/annotation → annotation}/tests/test_minio copy.py +0 -0
  90. /isa_model/training/{llm_model/annotation → annotation}/tests/test_minio_upload.py +0 -0
  91. /isa_model/training/{llm_model/annotation → annotation}/views/annotation_controller.py +0 -0
  92. {isa_model-0.0.2.dist-info → isa_model-0.3.1.dist-info}/WHEEL +0 -0
  93. {isa_model-0.0.2.dist-info → isa_model-0.3.1.dist-info}/top_level.txt +0 -0
@@ -1,134 +1,206 @@
1
1
  from abc import ABC, abstractmethod
2
- from typing import Dict, Any, List, Union, Optional, AsyncGenerator, TypeVar
2
+ from typing import Dict, Any, List, Union, Optional, AsyncGenerator, Callable
3
3
  from isa_model.inference.services.base_service import BaseService
4
-
5
- T = TypeVar('T') # Generic type for responses
4
+ from isa_model.inference.services.llm.llm_adapter import AdapterManager
6
5
 
7
6
  class BaseLLMService(BaseService):
8
- """Base class for Large Language Model services"""
7
+ """Base class for Large Language Model services with unified invoke interface"""
9
8
 
10
- @abstractmethod
11
- async def ainvoke(self, prompt: Union[str, List[Dict[str, str]], Any]) -> T:
12
- """
13
- Universal invocation method that handles different input types
9
+ def __init__(self, provider, model_name: str):
10
+ super().__init__(provider, model_name)
11
+ self._bound_tools: List[Any] = [] # 改为存储原始工具对象
12
+ self._tool_mappings: Dict[str, tuple] = {} # 工具名到(工具, 适配器)的映射
14
13
 
15
- Args:
16
- prompt: Can be a string, list of messages, or other format
17
-
18
- Returns:
19
- Model response in the appropriate format
20
- """
21
- pass
14
+ # 初始化适配器管理器
15
+ self.adapter_manager = AdapterManager()
16
+
17
+ # Get streaming config from provider config
18
+ self.streaming = self.config.get("streaming", False)
22
19
 
23
- @abstractmethod
24
- async def achat(self, messages: List[Dict[str, str]]) -> T:
20
+ def bind_tools(self, tools: List[Any], **kwargs) -> 'BaseLLMService':
25
21
  """
26
- Chat completion method using message format
22
+ Bind tools to this LLM service for function calling
27
23
 
28
24
  Args:
29
- messages: List of message dictionaries with 'role' and 'content' keys
30
- Example: [{"role": "user", "content": "Hello"}]
25
+ tools: List of tools to bind (functions, LangChain tools, etc.)
26
+ **kwargs: Additional tool binding parameters
31
27
 
32
28
  Returns:
33
- Chat completion response
29
+ Self for method chaining
34
30
  """
35
- pass
31
+ self._bound_tools = tools
32
+ return self
36
33
 
37
- @abstractmethod
38
- async def acompletion(self, prompt: str) -> T:
39
- """
40
- Text completion method for simple prompt completion
34
+ async def _prepare_tools_for_request(self) -> List[Dict[str, Any]]:
35
+ """准备工具用于请求"""
36
+ if not self._bound_tools:
37
+ return []
41
38
 
42
- Args:
43
- prompt: Input text prompt
44
-
45
- Returns:
46
- Text completion response
47
- """
48
- pass
39
+ schemas, self._tool_mappings = await self.adapter_manager.convert_tools_to_schemas(self._bound_tools)
40
+ return schemas
41
+
42
+ def _prepare_messages(self, input_data: Union[str, List[Dict[str, str]], Any]) -> List[Dict[str, str]]:
43
+ """使用适配器管理器转换消息格式"""
44
+ return self.adapter_manager.convert_messages(input_data)
45
+
46
+ def _format_response(self, response: str, original_input: Any) -> Union[str, Any]:
47
+ """使用适配器管理器格式化响应"""
48
+ return self.adapter_manager.format_response(response, original_input)
49
+
50
+ async def _execute_tool_call(self, tool_name: str, arguments: Dict[str, Any]) -> Any:
51
+ """使用适配器管理器执行工具调用"""
52
+ return await self.adapter_manager.execute_tool(tool_name, arguments, self._tool_mappings)
49
53
 
50
54
  @abstractmethod
51
- async def agenerate(self, messages: List[Dict[str, str]], n: int = 1) -> List[T]:
55
+ async def ainvoke(self, input_data: Union[str, List[Dict[str, str]], Any]) -> Union[str, Any]:
52
56
  """
53
- Generate multiple completions for the same input
57
+ Universal async invocation method that handles different input types
54
58
 
55
59
  Args:
56
- messages: List of message dictionaries
57
- n: Number of completions to generate
60
+ input_data: Can be:
61
+ - str: Simple text prompt
62
+ - list: Message history like [{"role": "user", "content": "hello"}]
63
+ - Any: LangChain message objects or other formats
58
64
 
59
65
  Returns:
60
- List of completion responses
66
+ Model response (string for simple cases, object for complex cases)
61
67
  """
62
68
  pass
63
69
 
64
- @abstractmethod
65
- async def astream_chat(self, messages: List[Dict[str, str]]) -> AsyncGenerator[str, None]:
70
+ def invoke(self, input_data: Union[str, List[Dict[str, str]], Any]) -> Union[str, Any]:
66
71
  """
67
- Stream chat responses token by token
72
+ Synchronous wrapper for ainvoke
68
73
 
69
74
  Args:
70
- messages: List of message dictionaries
75
+ input_data: Same as ainvoke
71
76
 
72
- Yields:
73
- Individual tokens or chunks of the response
74
- """
75
- pass
77
+ Returns:
78
+ Model response
79
+ """
80
+ import asyncio
81
+ try:
82
+ # Try to get current event loop
83
+ loop = asyncio.get_running_loop()
84
+ # If we're in an event loop, create a new thread
85
+ import concurrent.futures
86
+ with concurrent.futures.ThreadPoolExecutor() as executor:
87
+ future = executor.submit(asyncio.run, self.ainvoke(input_data))
88
+ return future.result()
89
+ except RuntimeError:
90
+ # No event loop running, create a new one
91
+ return asyncio.run(self.ainvoke(input_data))
76
92
 
77
- @abstractmethod
78
- async def astream_completion(self, prompt: str) -> AsyncGenerator[str, None]:
79
- """
80
- Stream completion responses token by token
93
+ # 保留旧的方法以保持向后兼容
94
+ def _convert_tools_to_schema(self, tools: List[Union[Dict[str, Any], Callable]]) -> List[Dict[str, Any]]:
95
+ """Convert tools to OpenAI function calling schema (deprecated, use adapter manager)"""
96
+ import asyncio
97
+ try:
98
+ loop = asyncio.get_event_loop()
99
+ schemas, _ = loop.run_until_complete(self.adapter_manager.convert_tools_to_schemas(tools))
100
+ return schemas
101
+ except RuntimeError:
102
+ schemas, _ = asyncio.run(self.adapter_manager.convert_tools_to_schemas(tools))
103
+ return schemas
104
+
105
+ def _has_bound_tools(self) -> bool:
106
+ """Check if this service has bound tools"""
107
+ return bool(self._bound_tools)
108
+
109
+ def _get_bound_tools(self) -> List[Dict[str, Any]]:
110
+ """Get the bound tools schema"""
111
+ return self._bound_tools
112
+
113
+ def _convert_langchain_to_openai(self, messages: List[Any]) -> List[Dict[str, str]]:
114
+ """Convert LangChain message objects to OpenAI format"""
115
+ converted_messages = []
81
116
 
82
- Args:
83
- prompt: Input text prompt
84
-
85
- Yields:
86
- Individual tokens or chunks of the response
87
- """
88
- pass
117
+ for msg in messages:
118
+ # Handle different LangChain message types
119
+ if hasattr(msg, 'type') and hasattr(msg, 'content'):
120
+ # LangChain message object
121
+ msg_dict = {"content": str(msg.content)}
122
+
123
+ # Map LangChain types to OpenAI roles
124
+ if msg.type == "system":
125
+ msg_dict["role"] = "system"
126
+ elif msg.type == "human":
127
+ msg_dict["role"] = "user"
128
+ elif msg.type == "ai":
129
+ msg_dict["role"] = "assistant"
130
+ # Handle tool calls if present
131
+ if hasattr(msg, 'tool_calls') and msg.tool_calls:
132
+ # Handle tool calls - need to store as separate key since it's not a string
133
+ tool_calls = [
134
+ {
135
+ "id": tc.get("id", f"call_{i}"),
136
+ "type": "function",
137
+ "function": {
138
+ "name": tc["name"],
139
+ "arguments": tc.get("args", {}) if isinstance(tc.get("args"), dict) else tc.get("args", "{}")
140
+ }
141
+ } for i, tc in enumerate(msg.tool_calls)
142
+ ]
143
+ # Store tool_calls separately to avoid type issues
144
+ msg_dict["tool_calls"] = tool_calls # type: ignore
145
+ elif msg.type == "tool":
146
+ msg_dict["role"] = "tool"
147
+ if hasattr(msg, 'tool_call_id'):
148
+ msg_dict["tool_call_id"] = msg.tool_call_id
149
+ elif msg.type == "function": # Legacy function message
150
+ msg_dict["role"] = "function"
151
+ if hasattr(msg, 'name'):
152
+ msg_dict["name"] = msg.name
153
+ else:
154
+ msg_dict["role"] = "user" # Default fallback
155
+
156
+ converted_messages.append(msg_dict)
157
+
158
+ elif isinstance(msg, dict):
159
+ # Already in OpenAI format
160
+ converted_messages.append(msg)
161
+ else:
162
+ # Fallback: treat as user message
163
+ converted_messages.append({"role": "user", "content": str(msg)})
164
+
165
+ return converted_messages
89
166
 
90
167
  @abstractmethod
91
168
  def get_token_usage(self) -> Dict[str, Any]:
92
- """
93
- Get cumulative token usage statistics for this service instance
94
-
95
- Returns:
96
- Dict containing token usage information:
97
- - total_tokens: Total tokens used
98
- - prompt_tokens: Tokens used for prompts
99
- - completion_tokens: Tokens used for completions
100
- - requests_count: Number of requests made
101
- """
169
+ """Get cumulative token usage statistics"""
102
170
  pass
103
171
 
104
172
  @abstractmethod
105
173
  def get_last_token_usage(self) -> Dict[str, int]:
106
- """
107
- Get token usage from the last request
108
-
109
- Returns:
110
- Dict containing last request token usage:
111
- - prompt_tokens: Tokens in last prompt
112
- - completion_tokens: Tokens in last completion
113
- - total_tokens: Total tokens in last request
114
- """
174
+ """Get token usage from the last request"""
115
175
  pass
116
176
 
117
177
  @abstractmethod
118
178
  def get_model_info(self) -> Dict[str, Any]:
119
- """
120
- Get information about the current model
121
-
122
- Returns:
123
- Dict containing model information:
124
- - name: Model name
125
- - max_tokens: Maximum context length
126
- - supports_streaming: Whether streaming is supported
127
- - supports_functions: Whether function calling is supported
128
- """
179
+ """Get information about the current model"""
129
180
  pass
130
181
 
131
182
  @abstractmethod
132
183
  async def close(self):
133
184
  """Cleanup resources and close connections"""
134
185
  pass
186
+
187
+ def get_last_usage_with_cost(self) -> Dict[str, Any]:
188
+ """Get last request usage with cost information"""
189
+ usage = self.get_last_token_usage()
190
+
191
+ # Calculate cost using provider
192
+ if hasattr(self.provider, 'calculate_cost'):
193
+ cost = getattr(self.provider, 'calculate_cost')(
194
+ self.model_name,
195
+ usage["prompt_tokens"],
196
+ usage["completion_tokens"]
197
+ )
198
+ else:
199
+ cost = 0.0
200
+
201
+ return {
202
+ **usage,
203
+ "cost_usd": cost,
204
+ "model": self.model_name,
205
+ "provider": getattr(self.provider, 'name', 'unknown')
206
+ }