isa-model 0.3.1__tar.gz → 0.3.3__tar.gz
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-0.3.1 → isa_model-0.3.3}/PKG-INFO +1 -1
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/llm/base_llm_service.py +2 -68
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/llm/llm_adapter.py +78 -6
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/llm/ollama_llm_service.py +22 -77
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/llm/openai_llm_service.py +4 -81
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model.egg-info/PKG-INFO +1 -1
- {isa_model-0.3.1 → isa_model-0.3.3}/pyproject.toml +1 -1
- {isa_model-0.3.1 → isa_model-0.3.3}/MANIFEST.in +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/README.md +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/__init__.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/core/model_manager.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/core/model_registry.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/core/model_storage.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/core/storage/hf_storage.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/core/storage/local_storage.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/core/storage/minio_storage.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/deployment/__init__.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/deployment/core/__init__.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/deployment/core/deployment_config.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/deployment/core/deployment_manager.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/deployment/core/isa_deployment_service.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/deployment/gpu_int8_ds8/app/server.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/deployment/gpu_int8_ds8/scripts/test_client.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/deployment/gpu_int8_ds8/scripts/test_client_os.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/eval/__init__.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/eval/benchmarks.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/eval/factory.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/eval/metrics.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/__init__.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/adapter/unified_api.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/ai_factory.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/base.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/billing_tracker.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/providers/__init__.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/providers/base_provider.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/providers/ml_provider.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/providers/model_cache_manager.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/providers/ollama_provider.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/providers/openai_provider.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/providers/replicate_provider.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/providers/triton_provider.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/__init__.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/audio/base_stt_service.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/audio/base_tts_service.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/audio/openai_realtime_service.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/audio/openai_stt_service.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/audio/openai_tts_service.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/audio/replicate_tts_service.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/base_service.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/embedding/base_embed_service.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/embedding/ollama_embed_service.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/embedding/openai_embed_service.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/llm/__init__.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/llm/triton_llm_service.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/ml/base_ml_service.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/ml/sklearn_ml_service.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/others/table_transformer_service.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/vision/__init__.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/vision/base_image_gen_service.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/vision/base_vision_service.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/vision/helpers/image_utils.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/vision/helpers/text_splitter.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/vision/ollama_vision_service.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/vision/openai_vision_service.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/vision/replicate_image_gen_service.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/utils/conversion/bge_rerank_convert.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/utils/conversion/onnx_converter.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/utils/conversion/torch_converter.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/scripts/inference_tracker.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/scripts/mlflow_manager.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/scripts/model_registry.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/scripts/start_mlflow.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/scripts/training_tracker.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/training/__init__.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/training/annotation/annotation_schema.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/training/annotation/processors/annotation_processor.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/training/annotation/storage/dataset_manager.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/training/annotation/storage/dataset_schema.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/training/annotation/tests/test_annotation_flow.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/training/annotation/tests/test_minio copy.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/training/annotation/tests/test_minio_upload.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/training/annotation/views/annotation_controller.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/training/cloud/__init__.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/training/cloud/job_orchestrator.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/training/cloud/runpod_trainer.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/training/cloud/storage_manager.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/training/core/__init__.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/training/core/config.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/training/core/dataset.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/training/core/trainer.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/training/core/utils.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model/training/factory.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model.egg-info/SOURCES.txt +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model.egg-info/dependency_links.txt +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model.egg-info/requires.txt +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/isa_model.egg-info/top_level.txt +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/setup.cfg +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/setup.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/tests/test_all_services.py +0 -0
- {isa_model-0.3.1 → isa_model-0.3.3}/tests/test_training_setup.py +0 -0
@@ -90,80 +90,14 @@ class BaseLLMService(BaseService):
|
|
90
90
|
# No event loop running, create a new one
|
91
91
|
return asyncio.run(self.ainvoke(input_data))
|
92
92
|
|
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
93
|
def _has_bound_tools(self) -> bool:
|
106
94
|
"""Check if this service has bound tools"""
|
107
95
|
return bool(self._bound_tools)
|
108
96
|
|
109
|
-
def _get_bound_tools(self) -> List[
|
110
|
-
"""Get the bound tools
|
97
|
+
def _get_bound_tools(self) -> List[Any]:
|
98
|
+
"""Get the bound tools"""
|
111
99
|
return self._bound_tools
|
112
100
|
|
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 = []
|
116
|
-
|
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
|
166
|
-
|
167
101
|
@abstractmethod
|
168
102
|
def get_token_usage(self) -> Dict[str, Any]:
|
169
103
|
"""Get cumulative token usage statistics"""
|
@@ -89,6 +89,33 @@ class LangChainMessageAdapter:
|
|
89
89
|
msg_dict["role"] = "user"
|
90
90
|
elif msg.type == "ai":
|
91
91
|
msg_dict["role"] = "assistant"
|
92
|
+
# Handle tool calls if present in LangChain AI messages
|
93
|
+
if hasattr(msg, 'tool_calls') and msg.tool_calls:
|
94
|
+
tool_calls = []
|
95
|
+
for tc in msg.tool_calls:
|
96
|
+
if isinstance(tc, dict):
|
97
|
+
# LangChain format: {"name": "func", "args": {...}, "id": "..."}
|
98
|
+
tool_call = {
|
99
|
+
"id": tc.get("id", f"call_{len(tool_calls)}"),
|
100
|
+
"type": "function",
|
101
|
+
"function": {
|
102
|
+
"name": tc.get("name", "unknown"),
|
103
|
+
"arguments": json.dumps(tc.get("args", {}))
|
104
|
+
}
|
105
|
+
}
|
106
|
+
else:
|
107
|
+
# Handle other tool call formats
|
108
|
+
tool_call = {
|
109
|
+
"id": getattr(tc, 'id', f"call_{len(tool_calls)}"),
|
110
|
+
"type": "function",
|
111
|
+
"function": {
|
112
|
+
"name": getattr(tc, 'name', 'unknown'),
|
113
|
+
"arguments": json.dumps(getattr(tc, 'args', {}))
|
114
|
+
}
|
115
|
+
}
|
116
|
+
tool_calls.append(tool_call)
|
117
|
+
|
118
|
+
msg_dict["tool_calls"] = tool_calls # type: ignore
|
92
119
|
elif msg.type == "tool":
|
93
120
|
msg_dict["role"] = "tool"
|
94
121
|
if hasattr(msg, 'tool_call_id'):
|
@@ -100,18 +127,55 @@ class LangChainMessageAdapter:
|
|
100
127
|
|
101
128
|
return converted_messages
|
102
129
|
|
103
|
-
def from_openai_format(self, response: str, original_input: Any) -> Any:
|
130
|
+
def from_openai_format(self, response: Union[str, Any], original_input: Any) -> Any:
|
104
131
|
"""从 OpenAI 格式转换回 LangChain 格式"""
|
105
132
|
try:
|
106
133
|
from langchain_core.messages import AIMessage
|
107
|
-
|
134
|
+
|
135
|
+
# Handle response objects with tool_calls (OpenAI message objects)
|
136
|
+
if hasattr(response, 'tool_calls') and response.tool_calls:
|
137
|
+
# Convert OpenAI tool_calls to LangChain format
|
138
|
+
tool_calls = []
|
139
|
+
for tc in response.tool_calls:
|
140
|
+
tool_call = {
|
141
|
+
"name": tc.function.name,
|
142
|
+
"args": json.loads(tc.function.arguments),
|
143
|
+
"id": tc.id
|
144
|
+
}
|
145
|
+
tool_calls.append(tool_call)
|
146
|
+
|
147
|
+
return AIMessage(
|
148
|
+
content=response.content or "",
|
149
|
+
tool_calls=tool_calls
|
150
|
+
)
|
151
|
+
else:
|
152
|
+
# Handle simple string response
|
153
|
+
content = response if isinstance(response, str) else getattr(response, 'content', str(response))
|
154
|
+
return AIMessage(content=content)
|
155
|
+
|
108
156
|
except ImportError:
|
109
157
|
# 回退实现
|
110
158
|
class SimpleAIMessage:
|
111
|
-
def __init__(self, content):
|
159
|
+
def __init__(self, content, tool_calls=None):
|
112
160
|
self.content = content
|
113
161
|
self.type = "ai"
|
114
|
-
|
162
|
+
self.tool_calls = tool_calls or []
|
163
|
+
|
164
|
+
# Handle response objects with tool_calls
|
165
|
+
if hasattr(response, 'tool_calls') and response.tool_calls:
|
166
|
+
tool_calls = []
|
167
|
+
for tc in response.tool_calls:
|
168
|
+
tool_call = {
|
169
|
+
"name": tc.function.name,
|
170
|
+
"args": json.loads(tc.function.arguments),
|
171
|
+
"id": tc.id
|
172
|
+
}
|
173
|
+
tool_calls.append(tool_call)
|
174
|
+
|
175
|
+
return SimpleAIMessage(response.content or "", tool_calls)
|
176
|
+
else:
|
177
|
+
content = response if isinstance(response, str) else getattr(response, 'content', str(response))
|
178
|
+
return SimpleAIMessage(content)
|
115
179
|
|
116
180
|
|
117
181
|
class LangChainToolAdapter:
|
@@ -293,9 +357,17 @@ class StandardMessageAdapter:
|
|
293
357
|
else:
|
294
358
|
return [{"role": "user", "content": str(input_data)}]
|
295
359
|
|
296
|
-
def from_openai_format(self, response: str, original_input: Any) -> Any:
|
360
|
+
def from_openai_format(self, response: Union[str, Any], original_input: Any) -> Any:
|
297
361
|
"""从 OpenAI 格式转换回原始格式"""
|
298
|
-
|
362
|
+
# Handle response objects with tool_calls (preserve message object for compatibility)
|
363
|
+
if hasattr(response, 'tool_calls') and response.tool_calls:
|
364
|
+
# For standard format, we preserve the message object for tool_calls access
|
365
|
+
# This handles both OpenAI and Ollama message objects
|
366
|
+
return response
|
367
|
+
else:
|
368
|
+
# Handle simple string response
|
369
|
+
content = response if isinstance(response, str) else getattr(response, 'content', str(response))
|
370
|
+
return content
|
299
371
|
|
300
372
|
|
301
373
|
# ============= 适配器管理器 =============
|
@@ -8,7 +8,7 @@ from isa_model.inference.providers.base_provider import BaseProvider
|
|
8
8
|
logger = logging.getLogger(__name__)
|
9
9
|
|
10
10
|
class OllamaLLMService(BaseLLMService):
|
11
|
-
"""Ollama LLM service with unified invoke interface"""
|
11
|
+
"""Ollama LLM service with unified invoke interface and proper adapter support"""
|
12
12
|
|
13
13
|
def __init__(self, provider: 'BaseProvider', model_name: str = "llama3.2:3b-instruct-fp16"):
|
14
14
|
super().__init__(provider, model_name)
|
@@ -25,10 +25,6 @@ class OllamaLLMService(BaseLLMService):
|
|
25
25
|
self.last_token_usage = {"prompt_tokens": 0, "completion_tokens": 0, "total_tokens": 0}
|
26
26
|
self.total_token_usage = {"prompt_tokens": 0, "completion_tokens": 0, "total_tokens": 0, "requests_count": 0}
|
27
27
|
|
28
|
-
# Tool binding attributes
|
29
|
-
self._bound_tools: List[Any] = []
|
30
|
-
self._tool_binding_kwargs: Dict[str, Any] = {}
|
31
|
-
self._tool_functions: Dict[str, Callable] = {}
|
32
28
|
|
33
29
|
logger.info(f"Initialized OllamaLLMService with model {model_name} at {base_url}")
|
34
30
|
|
@@ -43,16 +39,13 @@ class OllamaLLMService(BaseLLMService):
|
|
43
39
|
"""Create a copy of this service for tool binding"""
|
44
40
|
bound_service = OllamaLLMService(self.provider, self.model_name)
|
45
41
|
bound_service._bound_tools = self._bound_tools.copy()
|
46
|
-
bound_service._tool_binding_kwargs = self._tool_binding_kwargs.copy()
|
47
|
-
bound_service._tool_functions = self._tool_functions.copy()
|
48
42
|
return bound_service
|
49
43
|
|
50
|
-
def bind_tools(self, tools: List[
|
44
|
+
def bind_tools(self, tools: List[Any], **kwargs) -> 'OllamaLLMService':
|
51
45
|
"""Bind tools to this LLM service for function calling"""
|
52
46
|
bound_service = self._create_bound_copy()
|
53
|
-
#
|
47
|
+
# Use base class method to bind tools
|
54
48
|
bound_service._bound_tools = tools
|
55
|
-
bound_service._tool_binding_kwargs = kwargs
|
56
49
|
|
57
50
|
return bound_service
|
58
51
|
|
@@ -73,7 +66,7 @@ class OllamaLLMService(BaseLLMService):
|
|
73
66
|
# Ensure client is available
|
74
67
|
self._ensure_client()
|
75
68
|
|
76
|
-
#
|
69
|
+
# Use adapter manager to prepare messages (consistent with OpenAI service)
|
77
70
|
messages = self._prepare_messages(input_data)
|
78
71
|
|
79
72
|
# Prepare request parameters
|
@@ -106,77 +99,36 @@ class OllamaLLMService(BaseLLMService):
|
|
106
99
|
if "eval_count" in result:
|
107
100
|
self._update_token_usage(result)
|
108
101
|
|
109
|
-
# Handle tool calls if present
|
102
|
+
# Handle tool calls if present - let adapter process the complete message
|
110
103
|
message = result["message"]
|
111
104
|
if "tool_calls" in message and message["tool_calls"]:
|
112
|
-
|
105
|
+
# Create message object similar to OpenAI format for adapter processing
|
106
|
+
message_obj = type('OllamaMessage', (), {
|
107
|
+
'content': message.get("content", ""),
|
108
|
+
'tool_calls': message["tool_calls"]
|
109
|
+
})()
|
110
|
+
# Pass the complete message object to adapter for proper tool_calls handling
|
111
|
+
return self._format_response(message_obj, input_data)
|
113
112
|
|
114
113
|
# Return appropriate format based on input type
|
115
|
-
return self._format_response(message
|
114
|
+
return self._format_response(message.get("content", ""), input_data)
|
116
115
|
|
117
116
|
except httpx.RequestError as e:
|
118
117
|
logger.error(f"HTTP request error in ainvoke: {e}")
|
119
118
|
raise
|
120
119
|
except Exception as e:
|
121
|
-
logger.error(f"Error in
|
120
|
+
logger.error(f"Error in chat completion: {e}")
|
122
121
|
raise
|
123
122
|
|
124
123
|
def _prepare_messages(self, input_data: Union[str, List[Dict[str, str]], Any]) -> List[Dict[str, str]]:
|
125
|
-
"""
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
raise ValueError("Empty message list provided")
|
133
|
-
|
134
|
-
# Check if it's LangChain messages or standard messages
|
135
|
-
first_msg = input_data[0]
|
136
|
-
if hasattr(first_msg, 'content') and hasattr(first_msg, 'type'):
|
137
|
-
# LangChain message objects - use base class method
|
138
|
-
return self._convert_langchain_to_openai(input_data)
|
139
|
-
elif isinstance(first_msg, dict):
|
140
|
-
# Standard message dictionaries
|
141
|
-
return input_data
|
142
|
-
else:
|
143
|
-
# List of strings or other formats
|
144
|
-
messages = []
|
145
|
-
for i, msg in enumerate(input_data):
|
146
|
-
if isinstance(msg, str):
|
147
|
-
role = "user" if i % 2 == 0 else "assistant"
|
148
|
-
messages.append({"role": role, "content": msg})
|
149
|
-
elif isinstance(msg, dict):
|
150
|
-
messages.append(msg)
|
151
|
-
else:
|
152
|
-
messages.append({"role": "user", "content": str(msg)})
|
153
|
-
return messages
|
154
|
-
|
155
|
-
else:
|
156
|
-
# Handle single LangChain message objects or other objects
|
157
|
-
if hasattr(input_data, 'content') and hasattr(input_data, 'type'):
|
158
|
-
return self._convert_langchain_to_openai([input_data])
|
159
|
-
else:
|
160
|
-
return [{"role": "user", "content": str(input_data)}]
|
124
|
+
"""Use adapter manager to convert messages (consistent with OpenAI service)"""
|
125
|
+
return self.adapter_manager.convert_messages(input_data)
|
126
|
+
|
127
|
+
|
128
|
+
def _format_response(self, response: Union[str, Any], original_input: Any) -> Union[str, Any]:
|
129
|
+
"""Use adapter manager to format response (consistent with OpenAI service)"""
|
130
|
+
return self.adapter_manager.format_response(response, original_input)
|
161
131
|
|
162
|
-
def _format_response(self, content: str, original_input: Any) -> Union[str, Any]:
|
163
|
-
"""Format response based on original input type"""
|
164
|
-
# For LangGraph compatibility, return AIMessage object if needed
|
165
|
-
if hasattr(original_input, 'type') or (isinstance(original_input, list) and
|
166
|
-
original_input and hasattr(original_input[0], 'type')):
|
167
|
-
try:
|
168
|
-
from langchain_core.messages import AIMessage
|
169
|
-
return AIMessage(content=content)
|
170
|
-
except ImportError:
|
171
|
-
# Fallback to simple object
|
172
|
-
class SimpleAIMessage:
|
173
|
-
def __init__(self, content):
|
174
|
-
self.content = content
|
175
|
-
self.type = "ai"
|
176
|
-
return SimpleAIMessage(content)
|
177
|
-
|
178
|
-
# Default to string
|
179
|
-
return content
|
180
132
|
|
181
133
|
async def _stream_response(self, payload: Dict[str, Any]) -> AsyncGenerator[str, None]:
|
182
134
|
"""Handle streaming responses"""
|
@@ -270,13 +222,6 @@ class OllamaLLMService(BaseLLMService):
|
|
270
222
|
"provider": "ollama"
|
271
223
|
}
|
272
224
|
|
273
|
-
def _has_bound_tools(self) -> bool:
|
274
|
-
"""Check if this service has bound tools"""
|
275
|
-
return bool(self._bound_tools)
|
276
|
-
|
277
|
-
def _get_bound_tools(self) -> List[Any]:
|
278
|
-
"""Get the bound tools schema"""
|
279
|
-
return self._bound_tools
|
280
225
|
|
281
226
|
async def close(self):
|
282
227
|
"""Close the HTTP client"""
|
@@ -285,4 +230,4 @@ class OllamaLLMService(BaseLLMService):
|
|
285
230
|
if not self.client.is_closed:
|
286
231
|
await self.client.aclose()
|
287
232
|
except Exception as e:
|
288
|
-
logger.warning(f"Error closing Ollama client: {e}")
|
233
|
+
logger.warning(f"Error closing Ollama client: {e}")
|
@@ -41,17 +41,11 @@ class OpenAILLMService(BaseLLMService):
|
|
41
41
|
self.last_token_usage = {"prompt_tokens": 0, "completion_tokens": 0, "total_tokens": 0}
|
42
42
|
self.total_token_usage = {"prompt_tokens": 0, "completion_tokens": 0, "total_tokens": 0, "requests_count": 0}
|
43
43
|
|
44
|
-
# Tool binding attributes
|
45
|
-
self._bound_tools: List[Dict[str, Any]] = []
|
46
|
-
self._tool_binding_kwargs: Dict[str, Any] = {}
|
47
|
-
self._tool_functions: Dict[str, Callable] = {}
|
48
44
|
|
49
45
|
def _create_bound_copy(self) -> 'OpenAILLMService':
|
50
46
|
"""Create a copy of this service for tool binding"""
|
51
47
|
bound_service = OpenAILLMService(self.provider, self.model_name)
|
52
48
|
bound_service._bound_tools = self._bound_tools.copy()
|
53
|
-
bound_service._tool_binding_kwargs = self._tool_binding_kwargs.copy()
|
54
|
-
bound_service._tool_functions = self._tool_functions.copy()
|
55
49
|
return bound_service
|
56
50
|
|
57
51
|
def bind_tools(self, tools: List[Any], **kwargs) -> 'OpenAILLMService':
|
@@ -68,7 +62,7 @@ class OpenAILLMService(BaseLLMService):
|
|
68
62
|
# Create a copy of this service
|
69
63
|
bound_service = self._create_bound_copy()
|
70
64
|
|
71
|
-
# Use
|
65
|
+
# Use base class method to bind tools
|
72
66
|
bound_service._bound_tools = tools
|
73
67
|
|
74
68
|
return bound_service
|
@@ -123,10 +117,10 @@ class OpenAILLMService(BaseLLMService):
|
|
123
117
|
self._update_token_usage(response.usage)
|
124
118
|
self._track_billing(response.usage)
|
125
119
|
|
126
|
-
# Handle tool calls if present
|
120
|
+
# Handle tool calls if present - let adapter process the complete message
|
127
121
|
if message.tool_calls:
|
128
|
-
|
129
|
-
return self._format_response(
|
122
|
+
# Pass the complete message object to adapter for proper tool_calls handling
|
123
|
+
return self._format_response(message, input_data)
|
130
124
|
|
131
125
|
# Return appropriate format based on input type
|
132
126
|
return self._format_response(message.content or "", input_data)
|
@@ -135,13 +129,6 @@ class OpenAILLMService(BaseLLMService):
|
|
135
129
|
logger.error(f"Error in ainvoke: {e}")
|
136
130
|
raise
|
137
131
|
|
138
|
-
def _prepare_messages(self, input_data: Union[str, List[Dict[str, str]], Any]) -> List[Dict[str, str]]:
|
139
|
-
"""使用适配器管理器转换消息格式(覆盖基类方法以保持兼容性)"""
|
140
|
-
return self.adapter_manager.convert_messages(input_data)
|
141
|
-
|
142
|
-
def _format_response(self, content: str, original_input: Any) -> Union[str, Any]:
|
143
|
-
"""使用适配器管理器格式化响应(覆盖基类方法以保持兼容性)"""
|
144
|
-
return self.adapter_manager.format_response(content, original_input)
|
145
132
|
|
146
133
|
async def _stream_response(self, kwargs: Dict[str, Any]) -> AsyncGenerator[str, None]:
|
147
134
|
"""Handle streaming responses"""
|
@@ -160,63 +147,6 @@ class OpenAILLMService(BaseLLMService):
|
|
160
147
|
|
161
148
|
return stream_generator()
|
162
149
|
|
163
|
-
async def _handle_tool_calls(self, assistant_message, original_messages: List[Dict[str, str]]) -> str:
|
164
|
-
"""Handle tool calls from the assistant using adapter manager"""
|
165
|
-
# Add assistant message with tool calls to conversation
|
166
|
-
messages = original_messages + [{
|
167
|
-
"role": "assistant",
|
168
|
-
"content": assistant_message.content or "",
|
169
|
-
"tool_calls": [
|
170
|
-
{
|
171
|
-
"id": tc.id,
|
172
|
-
"type": tc.type,
|
173
|
-
"function": {
|
174
|
-
"name": tc.function.name,
|
175
|
-
"arguments": tc.function.arguments
|
176
|
-
}
|
177
|
-
} for tc in assistant_message.tool_calls
|
178
|
-
]
|
179
|
-
}]
|
180
|
-
|
181
|
-
# Execute each tool call using adapter manager
|
182
|
-
for tool_call in assistant_message.tool_calls:
|
183
|
-
function_name = tool_call.function.name
|
184
|
-
arguments = json.loads(tool_call.function.arguments)
|
185
|
-
|
186
|
-
try:
|
187
|
-
# Use adapter manager to execute tool
|
188
|
-
result = await self._execute_tool_call(function_name, arguments)
|
189
|
-
|
190
|
-
# Add tool result to messages
|
191
|
-
messages.append({
|
192
|
-
"role": "tool",
|
193
|
-
"content": str(result),
|
194
|
-
"tool_call_id": tool_call.id
|
195
|
-
})
|
196
|
-
|
197
|
-
except Exception as e:
|
198
|
-
logger.error(f"Error executing tool {function_name}: {e}")
|
199
|
-
messages.append({
|
200
|
-
"role": "tool",
|
201
|
-
"content": f"Error executing {function_name}: {str(e)}",
|
202
|
-
"tool_call_id": tool_call.id
|
203
|
-
})
|
204
|
-
|
205
|
-
# Get final response from the model
|
206
|
-
try:
|
207
|
-
kwargs = {
|
208
|
-
"model": self.model_name,
|
209
|
-
"messages": messages,
|
210
|
-
"temperature": self.config.get("temperature", 0.7),
|
211
|
-
"max_tokens": self.config.get("max_tokens", 1024)
|
212
|
-
}
|
213
|
-
|
214
|
-
response = await self.client.chat.completions.create(**kwargs)
|
215
|
-
return response.choices[0].message.content or ""
|
216
|
-
|
217
|
-
except Exception as e:
|
218
|
-
logger.error(f"Error getting final response after tool calls: {e}")
|
219
|
-
raise
|
220
150
|
|
221
151
|
def _update_token_usage(self, usage):
|
222
152
|
"""Update token usage statistics"""
|
@@ -263,13 +193,6 @@ class OpenAILLMService(BaseLLMService):
|
|
263
193
|
"provider": "openai"
|
264
194
|
}
|
265
195
|
|
266
|
-
def _has_bound_tools(self) -> bool:
|
267
|
-
"""Check if this service has bound tools"""
|
268
|
-
return bool(self._bound_tools)
|
269
|
-
|
270
|
-
def _get_bound_tools(self) -> List[Dict[str, Any]]:
|
271
|
-
"""Get the bound tools schema"""
|
272
|
-
return self._bound_tools
|
273
196
|
|
274
197
|
async def close(self):
|
275
198
|
"""Close the backend client"""
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{isa_model-0.3.1 → isa_model-0.3.3}/isa_model/deployment/gpu_int8_ds8/scripts/test_client.py
RENAMED
File without changes
|
{isa_model-0.3.1 → isa_model-0.3.3}/isa_model/deployment/gpu_int8_ds8/scripts/test_client_os.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/audio/openai_realtime_service.py
RENAMED
File without changes
|
{isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/audio/openai_stt_service.py
RENAMED
File without changes
|
{isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/audio/openai_tts_service.py
RENAMED
File without changes
|
{isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/audio/replicate_tts_service.py
RENAMED
File without changes
|
File without changes
|
{isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/embedding/base_embed_service.py
RENAMED
File without changes
|
{isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/embedding/ollama_embed_service.py
RENAMED
File without changes
|
{isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/embedding/openai_embed_service.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/others/table_transformer_service.py
RENAMED
File without changes
|
File without changes
|
{isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/vision/base_image_gen_service.py
RENAMED
File without changes
|
{isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/vision/base_vision_service.py
RENAMED
File without changes
|
{isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/vision/helpers/image_utils.py
RENAMED
File without changes
|
{isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/vision/helpers/text_splitter.py
RENAMED
File without changes
|
{isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/vision/ollama_vision_service.py
RENAMED
File without changes
|
{isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/services/vision/openai_vision_service.py
RENAMED
File without changes
|
File without changes
|
{isa_model-0.3.1 → isa_model-0.3.3}/isa_model/inference/utils/conversion/bge_rerank_convert.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{isa_model-0.3.1 → isa_model-0.3.3}/isa_model/training/annotation/processors/annotation_processor.py
RENAMED
File without changes
|
{isa_model-0.3.1 → isa_model-0.3.3}/isa_model/training/annotation/storage/dataset_manager.py
RENAMED
File without changes
|
File without changes
|
{isa_model-0.3.1 → isa_model-0.3.3}/isa_model/training/annotation/tests/test_annotation_flow.py
RENAMED
File without changes
|
File without changes
|
{isa_model-0.3.1 → isa_model-0.3.3}/isa_model/training/annotation/tests/test_minio_upload.py
RENAMED
File without changes
|
{isa_model-0.3.1 → isa_model-0.3.3}/isa_model/training/annotation/views/annotation_controller.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|