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
@@ -252,7 +252,8 @@ class YydsLLMService(BaseLLMService):
252
252
  async def chat(
253
253
  self,
254
254
  input_data: Union[str, List[Dict[str, str]], Any],
255
- max_tokens: Optional[int] = None
255
+ max_tokens: Optional[int] = None,
256
+ show_reasoning: bool = False
256
257
  ) -> Dict[str, Any]:
257
258
  """
258
259
  Chat method that wraps ainvoke for compatibility with base class
@@ -11,9 +11,9 @@ from .base_vision_service import BaseVisionService
11
11
  from .openai_vision_service import OpenAIVisionService
12
12
  from .replicate_vision_service import ReplicateVisionService
13
13
 
14
- # Stacked Vision Services
15
- from .doc_analysis_service import DocAnalysisStackedService
16
- from .ui_analysis_service import UIAnalysisService
14
+ # Stacked Vision Services (disabled - files don't exist)
15
+ # from .doc_analysis_service import DocAnalysisStackedService
16
+ # from .ui_analysis_service import UIAnalysisService
17
17
 
18
18
  # ISA Vision service
19
19
  try:
@@ -35,8 +35,8 @@ __all__ = [
35
35
  "BaseVisionService",
36
36
  "OpenAIVisionService",
37
37
  "ReplicateVisionService",
38
- "DocAnalysisStackedService",
39
- "UIAnalysisService"
38
+ # "DocAnalysisStackedService", # Disabled - file doesn't exist
39
+ # "UIAnalysisService" # Disabled - file doesn't exist
40
40
  ]
41
41
 
42
42
  if ISA_VISION_AVAILABLE:
@@ -21,43 +21,61 @@ class BaseVisionService(BaseService):
21
21
  **kwargs
22
22
  ) -> Dict[str, Any]:
23
23
  """
24
- 统一的任务分发方法 - Base类提供通用实现
24
+ 统一的任务分发方法 - 基于6个核心任务的设计
25
25
 
26
26
  Args:
27
27
  image: Path to image file or image data
28
28
  prompt: Optional text prompt/question about the image
29
- task: Task type - 支持两大类:图像理解 + 检测抽取
30
- **kwargs: Additional task-specific parameters
29
+ task: Core task type (analyze, describe, extract, detect, classify, compare)
30
+ **kwargs: Additional task-specific parameters including:
31
+ - target: Sub-task specification (e.g., "text"/"table" for extract, "objects"/"ui" for detect)
32
+ - max_tokens: Maximum tokens for text generation
33
+ - confidence_threshold: Confidence threshold for detection
34
+ - categories: Categories for classification
35
+ - image2: Second image for comparison
31
36
 
32
37
  Returns:
33
38
  Dict containing task results
34
39
  """
35
40
  task = task or "analyze"
36
41
 
37
- # ==================== 图像理解类任务 ====================
38
- if task == "analyze":
42
+ # Core task dispatch with parameterized sub-tasks
43
+ if task == "analyze" and hasattr(self, 'analyze_image'):
39
44
  return await self.analyze_image(image, prompt, kwargs.get("max_tokens", 1000))
40
- elif task == "describe":
45
+
46
+ elif task == "describe" and hasattr(self, 'describe_image'):
41
47
  return await self.describe_image(image, kwargs.get("detail_level", "medium"))
42
- elif task == "classify":
48
+
49
+ elif task == "extract":
50
+ # Extract with target specification
51
+ target = kwargs.get("target", "text")
52
+ if target == "table" and hasattr(self, 'extract_table_data'):
53
+ return await self.extract_table_data(image, kwargs.get("table_format", "json"))
54
+ elif hasattr(self, 'extract_text'):
55
+ return await self.extract_text(image)
56
+ else:
57
+ raise NotImplementedError(f"{self.__class__.__name__} does not support extract task")
58
+
59
+ elif task == "detect":
60
+ # Detect with target specification
61
+ target = kwargs.get("target", "objects")
62
+ if target == "ui" and hasattr(self, 'detect_ui_elements'):
63
+ return await self.detect_ui_elements(image,
64
+ kwargs.get("element_types"),
65
+ kwargs.get("confidence_threshold", 0.5))
66
+ elif target == "coordinates" and hasattr(self, 'get_object_coordinates'):
67
+ return await self.get_object_coordinates(image, kwargs.get("object_name", ""))
68
+ elif hasattr(self, 'detect_objects'):
69
+ return await self.detect_objects(image, kwargs.get("confidence_threshold", 0.5))
70
+ else:
71
+ raise NotImplementedError(f"{self.__class__.__name__} does not support detect task")
72
+
73
+ elif task == "classify" and hasattr(self, 'classify_image'):
43
74
  return await self.classify_image(image, kwargs.get("categories"))
44
- elif task == "compare":
75
+
76
+ elif task == "compare" and hasattr(self, 'compare_images'):
45
77
  return await self.compare_images(image, kwargs.get("image2"))
46
-
47
- # ==================== 检测抽取类任务 ====================
48
- elif task == "extract_text":
49
- return await self.extract_text(image)
50
- elif task == "detect_objects":
51
- return await self.detect_objects(image, kwargs.get("confidence_threshold", 0.5))
52
- elif task == "detect_ui_elements":
53
- return await self.detect_ui_elements(image, kwargs.get("element_types"), kwargs.get("confidence_threshold", 0.5))
54
- elif task == "detect_document_elements":
55
- return await self.detect_document_elements(image, kwargs.get("element_types"), kwargs.get("confidence_threshold", 0.5))
56
- elif task == "extract_table_data":
57
- return await self.extract_table_data(image, kwargs.get("table_format", "json"), kwargs.get("preserve_formatting", True))
58
- elif task == "get_coordinates":
59
- return await self.get_object_coordinates(image, kwargs.get("object_name", ""))
60
-
78
+
61
79
  else:
62
80
  raise NotImplementedError(f"{self.__class__.__name__} does not support task: {task}")
63
81
 
@@ -83,40 +101,84 @@ class BaseVisionService(BaseService):
83
101
  - metadata: Additional metadata about the analysis
84
102
  """
85
103
  raise NotImplementedError(f"{self.__class__.__name__} does not support analyze_image task")
104
+
86
105
 
87
- # ==================== 图像理解类方法 ====================
88
106
 
89
- async def describe_image(
90
- self,
91
- image: Union[str, BinaryIO],
92
- detail_level: str = "medium"
93
- ) -> Dict[str, Any]:
107
+
108
+ async def close(self):
109
+ """Cleanup resources - default implementation does nothing"""
110
+ pass
111
+
112
+ def get_supported_tasks(self) -> List[str]:
94
113
  """
95
- 图像描述 - Provider可选实现
114
+ 获取provider支持的核心任务列表
115
+
116
+ Returns:
117
+ List of core task names (analyze, describe, extract, detect, classify, compare)
96
118
  """
97
- raise NotImplementedError(f"{self.__class__.__name__} does not support describe_image task")
119
+ supported = []
120
+
121
+ # Check core task support based on implemented methods
122
+ task_method_map = {
123
+ 'analyze': 'analyze_image',
124
+ 'describe': 'describe_image',
125
+ 'extract': 'extract_text', # Basic extract support
126
+ 'detect': 'detect_objects', # Basic detect support
127
+ 'classify': 'classify_image',
128
+ 'compare': 'compare_images'
129
+ }
130
+
131
+ for task_name, method_name in task_method_map.items():
132
+ if hasattr(self, method_name):
133
+ try:
134
+ # Check if method is actually implemented (not just raising NotImplementedError)
135
+ import inspect
136
+ method = getattr(self, method_name)
137
+ if callable(method):
138
+ source = inspect.getsource(method)
139
+ # If it's not just raising NotImplementedError, consider it supported
140
+ if not ('raise NotImplementedError' in source and len(source.split('\n')) < 10):
141
+ supported.append(task_name)
142
+ except:
143
+ # If we can't inspect, assume it's supported if the method exists
144
+ supported.append(task_name)
145
+
146
+ return supported
98
147
 
99
- async def classify_image(
148
+ # ==================== COMMON TASK IMPLEMENTATIONS ====================
149
+ # 为每个provider提供可选的默认实现,provider可以覆盖这些方法
150
+
151
+ async def analyze_images(
100
152
  self,
101
- image: Union[str, BinaryIO],
102
- categories: Optional[List[str]] = None
103
- ) -> Dict[str, Any]:
153
+ images: List[Union[str, BinaryIO]],
154
+ prompt: Optional[str] = None,
155
+ max_tokens: int = 1000
156
+ ) -> List[Dict[str, Any]]:
104
157
  """
105
- 图像分类 - Provider可选实现
158
+ 批量图像分析 - Provider可选实现
159
+ 默认实现:如果provider支持analyze_image,则逐个调用
106
160
  """
107
- raise NotImplementedError(f"{self.__class__.__name__} does not support classify_image task")
161
+ if hasattr(self, 'analyze_image'):
162
+ results = []
163
+ for image in images:
164
+ try:
165
+ result = await self.analyze_image(image, prompt, max_tokens)
166
+ results.append(result)
167
+ except NotImplementedError:
168
+ raise NotImplementedError(f"{self.__class__.__name__} does not support analyze_images task")
169
+ return results
170
+ else:
171
+ raise NotImplementedError(f"{self.__class__.__name__} does not support analyze_images task")
108
172
 
109
- async def compare_images(
173
+ async def describe_image(
110
174
  self,
111
- image1: Union[str, BinaryIO],
112
- image2: Union[str, BinaryIO]
175
+ image: Union[str, BinaryIO],
176
+ detail_level: str = "medium"
113
177
  ) -> Dict[str, Any]:
114
178
  """
115
- 图像比较 - Provider可选实现
179
+ 图像描述 - Provider可选实现
116
180
  """
117
- raise NotImplementedError(f"{self.__class__.__name__} does not support compare_images task")
118
-
119
- # ==================== 检测抽取类方法 ====================
181
+ raise NotImplementedError(f"{self.__class__.__name__} does not support describe_image task")
120
182
 
121
183
  async def extract_text(self, image: Union[str, BinaryIO]) -> Dict[str, Any]:
122
184
  """
@@ -130,48 +192,10 @@ class BaseVisionService(BaseService):
130
192
  confidence_threshold: float = 0.5
131
193
  ) -> Dict[str, Any]:
132
194
  """
133
- 通用物体检测 - Provider可选实现
195
+ 物体检测 - Provider可选实现
134
196
  """
135
197
  raise NotImplementedError(f"{self.__class__.__name__} does not support detect_objects task")
136
198
 
137
- async def detect_ui_elements(
138
- self,
139
- image: Union[str, BinaryIO],
140
- element_types: Optional[List[str]] = None,
141
- confidence_threshold: float = 0.5
142
- ) -> Dict[str, Any]:
143
- """
144
- UI界面元素检测 - Provider可选实现
145
-
146
- Args:
147
- image: 输入图像
148
- element_types: 要检测的元素类型 ['button', 'input', 'text', 'image', 'link', etc.]
149
- confidence_threshold: 置信度阈值
150
-
151
- Returns:
152
- Dict containing detected UI elements with their bounding boxes and types
153
- """
154
- raise NotImplementedError(f"{self.__class__.__name__} does not support detect_ui_elements task")
155
-
156
- async def detect_document_elements(
157
- self,
158
- image: Union[str, BinaryIO],
159
- element_types: Optional[List[str]] = None,
160
- confidence_threshold: float = 0.5
161
- ) -> Dict[str, Any]:
162
- """
163
- 文档结构元素检测 - Provider可选实现
164
-
165
- Args:
166
- image: 输入图像
167
- element_types: 要检测的元素类型 ['table', 'header', 'paragraph', 'list', etc.]
168
- confidence_threshold: 置信度阈值
169
-
170
- Returns:
171
- Dict containing detected document elements with their structure and content
172
- """
173
- raise NotImplementedError(f"{self.__class__.__name__} does not support detect_document_elements task")
174
-
175
199
  async def get_object_coordinates(
176
200
  self,
177
201
  image: Union[str, BinaryIO],
@@ -182,116 +206,25 @@ class BaseVisionService(BaseService):
182
206
  """
183
207
  raise NotImplementedError(f"{self.__class__.__name__} does not support get_object_coordinates task")
184
208
 
185
- async def extract_table_data(
186
- self,
209
+ async def classify_image(
210
+ self,
187
211
  image: Union[str, BinaryIO],
188
- table_format: str = "json",
189
- preserve_formatting: bool = True
212
+ categories: Optional[List[str]] = None
190
213
  ) -> Dict[str, Any]:
191
214
  """
192
- 表格数据结构化抽取 - Provider可选实现
193
-
194
- Args:
195
- image: 输入图像
196
- table_format: 输出格式 ('json', 'csv', 'markdown', 'html')
197
- preserve_formatting: 是否保持原始格式(合并单元格、样式等)
198
-
199
- Returns:
200
- Dict containing extracted table data in structured format:
201
- {
202
- "tables": [
203
- {
204
- "table_id": "table_1",
205
- "headers": ["Column1", "Column2", "Column3"],
206
- "rows": [
207
- ["cell1", "cell2", "cell3"],
208
- ["cell4", "cell5", "cell6"]
209
- ],
210
- "metadata": {
211
- "row_count": 2,
212
- "column_count": 3,
213
- "has_headers": true,
214
- "merged_cells": [],
215
- "table_caption": "optional_caption"
216
- }
217
- }
218
- ],
219
- "raw_data": "original_table_text",
220
- "format": "json"
221
- }
222
- """
223
- raise NotImplementedError(f"{self.__class__.__name__} does not support extract_table_data task")
224
-
225
- async def close(self):
226
- """Cleanup resources - default implementation does nothing"""
227
- pass
228
-
229
- def get_supported_tasks(self) -> List[str]:
230
- """
231
- 获取provider支持的任务列表
232
-
233
- Returns:
234
- List of supported task names
215
+ 图像分类 - Provider可选实现
235
216
  """
236
- supported = []
237
-
238
- # 检查哪些方法被实现了
239
- if hasattr(self, 'analyze_image') and callable(getattr(self, 'analyze_image')):
240
- try:
241
- # 尝试调用看是否抛出NotImplementedError
242
- import inspect
243
- if not 'NotImplementedError' in inspect.getsource(self.analyze_image):
244
- supported.append('analyze')
245
- except:
246
- pass
247
-
248
- # 检查各类任务支持情况
249
- method_task_map = {
250
- # 图像理解类
251
- 'describe_image': 'describe',
252
- 'classify_image': 'classify',
253
- 'compare_images': 'compare',
254
- # 检测抽取类
255
- 'extract_text': 'extract_text',
256
- 'detect_objects': 'detect_objects',
257
- 'detect_ui_elements': 'detect_ui_elements',
258
- 'detect_document_elements': 'detect_document_elements',
259
- 'extract_table_data': 'extract_table_data',
260
- 'get_object_coordinates': 'get_coordinates'
261
- }
262
-
263
- for method_name, task_name in method_task_map.items():
264
- if hasattr(self, method_name):
265
- # 检查是否是默认实现(基于analyze_image)还是provider自己的实现
266
- supported.append(task_name)
267
-
268
- return supported
269
-
270
- # ==================== COMMON TASK IMPLEMENTATIONS ====================
271
- # 为每个provider提供可选的默认实现,provider可以覆盖这些方法
217
+ raise NotImplementedError(f"{self.__class__.__name__} does not support classify_image task")
272
218
 
273
- async def analyze_images(
219
+ async def compare_images(
274
220
  self,
275
- images: List[Union[str, BinaryIO]],
276
- prompt: Optional[str] = None,
277
- max_tokens: int = 1000
278
- ) -> List[Dict[str, Any]]:
221
+ image1: Union[str, BinaryIO],
222
+ image2: Union[str, BinaryIO]
223
+ ) -> Dict[str, Any]:
279
224
  """
280
- 批量图像分析 - Provider可选实现
281
- 默认实现:如果provider支持analyze_image,则逐个调用
225
+ 图像比较 - Provider可选实现
282
226
  """
283
- if hasattr(self, 'analyze_image'):
284
- results = []
285
- for image in images:
286
- try:
287
- result = await self.analyze_image(image, prompt, max_tokens)
288
- results.append(result)
289
- except NotImplementedError:
290
- raise NotImplementedError(f"{self.__class__.__name__} does not support analyze_images task")
291
- return results
292
- else:
293
- raise NotImplementedError(f"{self.__class__.__name__} does not support analyze_images task")
294
-
227
+ raise NotImplementedError(f"{self.__class__.__name__} does not support compare_images task")
295
228
 
296
229
  def get_supported_formats(self) -> List[str]:
297
230
  """
@@ -27,16 +27,22 @@ def get_image_data(image: Union[str, BinaryIO]) -> bytes:
27
27
  return response.content
28
28
  elif image.startswith('data:'):
29
29
  # Data URL格式 (如 data:image/png;base64,...)
30
- import base64
31
30
  if 'base64,' in image:
32
31
  base64_data = image.split('base64,')[1]
33
32
  return base64.b64decode(base64_data)
34
33
  else:
35
34
  raise ValueError("Unsupported data URL format")
36
- else:
37
- # 本地文件路径
38
- with open(image, 'rb') as f:
39
- return f.read()
35
+ elif len(image) > 100 and not os.path.exists(image):
36
+ # 纯base64字符串 (没有data URL前缀)
37
+ try:
38
+ return base64.b64decode(image)
39
+ except Exception:
40
+ # 如果base64解码失败,则当作文件路径处理
41
+ pass
42
+
43
+ # 本地文件路径
44
+ with open(image, 'rb') as f:
45
+ return f.read()
40
46
  elif hasattr(image, 'read'):
41
47
  # 文件类对象
42
48
  data = image.read()