isa-model 0.4.0__py3-none-any.whl → 0.4.4__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 (189) hide show
  1. isa_model/client.py +466 -43
  2. isa_model/core/cache/redis_cache.py +12 -3
  3. isa_model/core/config/config_manager.py +230 -3
  4. isa_model/core/config.py +90 -0
  5. isa_model/core/database/direct_db_client.py +114 -0
  6. isa_model/core/database/migration_manager.py +563 -0
  7. isa_model/core/database/migrations.py +21 -1
  8. isa_model/core/database/supabase_client.py +154 -19
  9. isa_model/core/dependencies.py +316 -0
  10. isa_model/core/discovery/__init__.py +19 -0
  11. isa_model/core/discovery/consul_discovery.py +190 -0
  12. isa_model/core/logging/__init__.py +54 -0
  13. isa_model/core/logging/influx_logger.py +523 -0
  14. isa_model/core/logging/loki_logger.py +160 -0
  15. isa_model/core/models/__init__.py +27 -18
  16. isa_model/core/models/config_models.py +625 -0
  17. isa_model/core/models/deployment_billing_tracker.py +430 -0
  18. isa_model/core/models/model_manager.py +35 -80
  19. isa_model/core/models/model_metadata.py +690 -0
  20. isa_model/core/models/model_repo.py +174 -18
  21. isa_model/core/models/system_models.py +857 -0
  22. isa_model/core/repositories/__init__.py +9 -0
  23. isa_model/core/repositories/config_repository.py +912 -0
  24. isa_model/core/services/intelligent_model_selector.py +399 -21
  25. isa_model/core/types.py +1 -0
  26. isa_model/deployment/__init__.py +5 -48
  27. isa_model/deployment/core/__init__.py +2 -31
  28. isa_model/deployment/core/deployment_manager.py +1278 -370
  29. isa_model/deployment/modal/__init__.py +8 -0
  30. isa_model/deployment/modal/config.py +136 -0
  31. isa_model/deployment/{services/auto_hf_modal_deployer.py → modal/deployer.py} +1 -1
  32. isa_model/deployment/modal/services/__init__.py +3 -0
  33. isa_model/deployment/modal/services/audio/__init__.py +1 -0
  34. isa_model/deployment/modal/services/embedding/__init__.py +1 -0
  35. isa_model/deployment/modal/services/llm/__init__.py +1 -0
  36. isa_model/deployment/modal/services/llm/isa_llm_service.py +424 -0
  37. isa_model/deployment/modal/services/video/__init__.py +1 -0
  38. isa_model/deployment/modal/services/vision/__init__.py +1 -0
  39. isa_model/deployment/models/org-org-acme-corp-tenant-a-service-llm-20250825-225822/tenant-a-service_modal_service.py +48 -0
  40. isa_model/deployment/models/org-test-org-123-prefix-test-service-llm-20250825-225822/prefix-test-service_modal_service.py +48 -0
  41. isa_model/deployment/models/test-llm-service-llm-20250825-204442/test-llm-service_modal_service.py +48 -0
  42. isa_model/deployment/models/test-monitoring-gpt2-llm-20250825-212906/test-monitoring-gpt2_modal_service.py +48 -0
  43. isa_model/deployment/models/test-monitoring-gpt2-llm-20250825-213009/test-monitoring-gpt2_modal_service.py +48 -0
  44. isa_model/deployment/storage/__init__.py +5 -0
  45. isa_model/deployment/storage/deployment_repository.py +824 -0
  46. isa_model/deployment/triton/__init__.py +10 -0
  47. isa_model/deployment/triton/config.py +196 -0
  48. isa_model/deployment/triton/configs/__init__.py +1 -0
  49. isa_model/deployment/triton/provider.py +512 -0
  50. isa_model/deployment/triton/scripts/__init__.py +1 -0
  51. isa_model/deployment/triton/templates/__init__.py +1 -0
  52. isa_model/inference/__init__.py +47 -1
  53. isa_model/inference/ai_factory.py +137 -10
  54. isa_model/inference/legacy_services/__init__.py +21 -0
  55. isa_model/inference/legacy_services/model_evaluation.py +637 -0
  56. isa_model/inference/legacy_services/model_service.py +573 -0
  57. isa_model/inference/legacy_services/model_serving.py +717 -0
  58. isa_model/inference/legacy_services/model_training.py +561 -0
  59. isa_model/inference/models/__init__.py +21 -0
  60. isa_model/inference/models/inference_config.py +551 -0
  61. isa_model/inference/models/inference_record.py +675 -0
  62. isa_model/inference/models/performance_models.py +714 -0
  63. isa_model/inference/repositories/__init__.py +9 -0
  64. isa_model/inference/repositories/inference_repository.py +828 -0
  65. isa_model/inference/services/audio/base_stt_service.py +184 -11
  66. isa_model/inference/services/audio/openai_stt_service.py +22 -6
  67. isa_model/inference/services/embedding/ollama_embed_service.py +15 -3
  68. isa_model/inference/services/embedding/resilient_embed_service.py +285 -0
  69. isa_model/inference/services/llm/__init__.py +10 -2
  70. isa_model/inference/services/llm/base_llm_service.py +335 -24
  71. isa_model/inference/services/llm/cerebras_llm_service.py +628 -0
  72. isa_model/inference/services/llm/helpers/llm_adapter.py +9 -4
  73. isa_model/inference/services/llm/helpers/llm_prompts.py +342 -0
  74. isa_model/inference/services/llm/helpers/llm_utils.py +321 -23
  75. isa_model/inference/services/llm/huggingface_llm_service.py +581 -0
  76. isa_model/inference/services/llm/ollama_llm_service.py +9 -2
  77. isa_model/inference/services/llm/openai_llm_service.py +33 -16
  78. isa_model/inference/services/llm/yyds_llm_service.py +8 -2
  79. isa_model/inference/services/vision/__init__.py +22 -1
  80. isa_model/inference/services/vision/helpers/image_utils.py +8 -5
  81. isa_model/inference/services/vision/isa_vision_service.py +65 -4
  82. isa_model/inference/services/vision/openai_vision_service.py +19 -10
  83. isa_model/inference/services/vision/vgg16_vision_service.py +257 -0
  84. isa_model/serving/api/cache_manager.py +245 -0
  85. isa_model/serving/api/dependencies/__init__.py +1 -0
  86. isa_model/serving/api/dependencies/auth.py +194 -0
  87. isa_model/serving/api/dependencies/database.py +139 -0
  88. isa_model/serving/api/error_handlers.py +284 -0
  89. isa_model/serving/api/fastapi_server.py +172 -22
  90. isa_model/serving/api/middleware/auth.py +8 -2
  91. isa_model/serving/api/middleware/security.py +23 -33
  92. isa_model/serving/api/middleware/tenant_context.py +414 -0
  93. isa_model/serving/api/routes/analytics.py +4 -1
  94. isa_model/serving/api/routes/config.py +645 -0
  95. isa_model/serving/api/routes/deployment_billing.py +315 -0
  96. isa_model/serving/api/routes/deployments.py +138 -2
  97. isa_model/serving/api/routes/gpu_gateway.py +440 -0
  98. isa_model/serving/api/routes/health.py +32 -12
  99. isa_model/serving/api/routes/inference_monitoring.py +486 -0
  100. isa_model/serving/api/routes/local_deployments.py +448 -0
  101. isa_model/serving/api/routes/tenants.py +575 -0
  102. isa_model/serving/api/routes/unified.py +680 -18
  103. isa_model/serving/api/routes/webhooks.py +479 -0
  104. isa_model/serving/api/startup.py +68 -54
  105. isa_model/utils/gpu_utils.py +311 -0
  106. {isa_model-0.4.0.dist-info → isa_model-0.4.4.dist-info}/METADATA +71 -24
  107. isa_model-0.4.4.dist-info/RECORD +180 -0
  108. isa_model/core/security/secrets.py +0 -358
  109. isa_model/core/storage/hf_storage.py +0 -419
  110. isa_model/core/storage/minio_storage.py +0 -0
  111. isa_model/deployment/cloud/__init__.py +0 -9
  112. isa_model/deployment/cloud/modal/__init__.py +0 -10
  113. isa_model/deployment/core/deployment_config.py +0 -356
  114. isa_model/deployment/core/isa_deployment_service.py +0 -401
  115. isa_model/deployment/gpu_int8_ds8/app/server.py +0 -66
  116. isa_model/deployment/gpu_int8_ds8/scripts/test_client.py +0 -43
  117. isa_model/deployment/gpu_int8_ds8/scripts/test_client_os.py +0 -35
  118. isa_model/deployment/runtime/deployed_service.py +0 -338
  119. isa_model/deployment/services/__init__.py +0 -9
  120. isa_model/deployment/services/auto_deploy_vision_service.py +0 -538
  121. isa_model/deployment/services/model_service.py +0 -332
  122. isa_model/deployment/services/service_monitor.py +0 -356
  123. isa_model/deployment/services/service_registry.py +0 -527
  124. isa_model/eval/__init__.py +0 -92
  125. isa_model/eval/benchmarks/__init__.py +0 -27
  126. isa_model/eval/benchmarks/multimodal_datasets.py +0 -460
  127. isa_model/eval/benchmarks.py +0 -701
  128. isa_model/eval/config/__init__.py +0 -10
  129. isa_model/eval/config/evaluation_config.py +0 -108
  130. isa_model/eval/evaluators/__init__.py +0 -24
  131. isa_model/eval/evaluators/audio_evaluator.py +0 -727
  132. isa_model/eval/evaluators/base_evaluator.py +0 -503
  133. isa_model/eval/evaluators/embedding_evaluator.py +0 -742
  134. isa_model/eval/evaluators/llm_evaluator.py +0 -472
  135. isa_model/eval/evaluators/vision_evaluator.py +0 -564
  136. isa_model/eval/example_evaluation.py +0 -395
  137. isa_model/eval/factory.py +0 -798
  138. isa_model/eval/infrastructure/__init__.py +0 -24
  139. isa_model/eval/infrastructure/experiment_tracker.py +0 -466
  140. isa_model/eval/isa_benchmarks.py +0 -700
  141. isa_model/eval/isa_integration.py +0 -582
  142. isa_model/eval/metrics.py +0 -951
  143. isa_model/eval/tests/unit/test_basic.py +0 -396
  144. isa_model/serving/api/routes/evaluations.py +0 -579
  145. isa_model/training/__init__.py +0 -168
  146. isa_model/training/annotation/annotation_schema.py +0 -47
  147. isa_model/training/annotation/processors/annotation_processor.py +0 -126
  148. isa_model/training/annotation/storage/dataset_manager.py +0 -131
  149. isa_model/training/annotation/storage/dataset_schema.py +0 -44
  150. isa_model/training/annotation/tests/test_annotation_flow.py +0 -109
  151. isa_model/training/annotation/tests/test_minio copy.py +0 -113
  152. isa_model/training/annotation/tests/test_minio_upload.py +0 -43
  153. isa_model/training/annotation/views/annotation_controller.py +0 -158
  154. isa_model/training/cloud/__init__.py +0 -22
  155. isa_model/training/cloud/job_orchestrator.py +0 -402
  156. isa_model/training/cloud/runpod_trainer.py +0 -454
  157. isa_model/training/cloud/storage_manager.py +0 -482
  158. isa_model/training/core/__init__.py +0 -26
  159. isa_model/training/core/config.py +0 -181
  160. isa_model/training/core/dataset.py +0 -222
  161. isa_model/training/core/trainer.py +0 -720
  162. isa_model/training/core/utils.py +0 -213
  163. isa_model/training/examples/intelligent_training_example.py +0 -281
  164. isa_model/training/factory.py +0 -424
  165. isa_model/training/intelligent/__init__.py +0 -25
  166. isa_model/training/intelligent/decision_engine.py +0 -643
  167. isa_model/training/intelligent/intelligent_factory.py +0 -888
  168. isa_model/training/intelligent/knowledge_base.py +0 -751
  169. isa_model/training/intelligent/resource_optimizer.py +0 -839
  170. isa_model/training/intelligent/task_classifier.py +0 -576
  171. isa_model/training/storage/__init__.py +0 -24
  172. isa_model/training/storage/core_integration.py +0 -439
  173. isa_model/training/storage/training_repository.py +0 -552
  174. isa_model/training/storage/training_storage.py +0 -628
  175. isa_model-0.4.0.dist-info/RECORD +0 -182
  176. /isa_model/deployment/{cloud/modal → modal/services/audio}/isa_audio_chatTTS_service.py +0 -0
  177. /isa_model/deployment/{cloud/modal → modal/services/audio}/isa_audio_fish_service.py +0 -0
  178. /isa_model/deployment/{cloud/modal → modal/services/audio}/isa_audio_openvoice_service.py +0 -0
  179. /isa_model/deployment/{cloud/modal → modal/services/audio}/isa_audio_service_v2.py +0 -0
  180. /isa_model/deployment/{cloud/modal → modal/services/embedding}/isa_embed_rerank_service.py +0 -0
  181. /isa_model/deployment/{cloud/modal → modal/services/video}/isa_video_hunyuan_service.py +0 -0
  182. /isa_model/deployment/{cloud/modal → modal/services/vision}/isa_vision_ocr_service.py +0 -0
  183. /isa_model/deployment/{cloud/modal → modal/services/vision}/isa_vision_qwen25_service.py +0 -0
  184. /isa_model/deployment/{cloud/modal → modal/services/vision}/isa_vision_table_service.py +0 -0
  185. /isa_model/deployment/{cloud/modal → modal/services/vision}/isa_vision_ui_service.py +0 -0
  186. /isa_model/deployment/{cloud/modal → modal/services/vision}/isa_vision_ui_service_optimized.py +0 -0
  187. /isa_model/deployment/{services → modal/services/vision}/simple_auto_deploy_vision_service.py +0 -0
  188. {isa_model-0.4.0.dist-info → isa_model-0.4.4.dist-info}/WHEEL +0 -0
  189. {isa_model-0.4.0.dist-info → isa_model-0.4.4.dist-info}/top_level.txt +0 -0
@@ -95,34 +95,332 @@ class TextProcessor:
95
95
  return code_blocks
96
96
 
97
97
  @staticmethod
98
- def extract_json_from_text(text: str) -> Optional[Dict[str, Any]]:
99
- """从文本中提取JSON"""
100
- # 尝试直接解析
101
- try:
102
- return json.loads(text)
103
- except json.JSONDecodeError:
104
- pass
98
+ def extract_json_from_text(text: str, schema: Optional[Dict] = None, repair_attempts: int = 3) -> Dict[str, Any]:
99
+ """Enhanced JSON extraction with validation and error recovery"""
100
+ result = {
101
+ "success": False,
102
+ "data": None,
103
+ "errors": [],
104
+ "method": None,
105
+ "repaired": False
106
+ }
105
107
 
106
- # 尝试提取JSON代码块
107
- json_pattern = r'```json\n(.*?)\n```'
108
- match = re.search(json_pattern, text, re.DOTALL)
109
- if match:
110
- try:
111
- return json.loads(match.group(1))
112
- except json.JSONDecodeError:
113
- pass
114
-
115
- # 尝试提取花括号内容
116
- brace_pattern = r'\{.*\}'
117
- match = re.search(brace_pattern, text, re.DOTALL)
118
- if match:
108
+ extraction_methods = [
109
+ ("direct_parse", TextProcessor._try_direct_json_parse),
110
+ ("json_code_block", TextProcessor._try_json_code_block),
111
+ ("first_json_object", TextProcessor._try_first_json_object),
112
+ ("between_braces", TextProcessor._try_between_braces),
113
+ ("multiple_objects", TextProcessor._try_multiple_json_objects),
114
+ ("yaml_like", TextProcessor._try_yaml_like_parsing)
115
+ ]
116
+
117
+ for method_name, extraction_func in extraction_methods:
119
118
  try:
120
- return json.loads(match.group(0))
121
- except json.JSONDecodeError:
122
- pass
119
+ extracted_data = extraction_func(text)
120
+ if extracted_data is not None:
121
+ # Validate against schema if provided
122
+ if schema:
123
+ validation_result = TextProcessor._validate_json_schema(extracted_data, schema)
124
+ if validation_result["valid"]:
125
+ result.update({
126
+ "success": True,
127
+ "data": extracted_data,
128
+ "method": method_name
129
+ })
130
+ return result
131
+ else:
132
+ result["errors"].append(f"{method_name}: {validation_result['error']}")
133
+ else:
134
+ result.update({
135
+ "success": True,
136
+ "data": extracted_data,
137
+ "method": method_name
138
+ })
139
+ return result
140
+ except Exception as e:
141
+ result["errors"].append(f"{method_name}: {str(e)}")
142
+ continue
143
+
144
+ # If all methods failed, try repair attempts
145
+ if repair_attempts > 0:
146
+ repair_result = TextProcessor._attempt_json_repair(text, schema, repair_attempts)
147
+ if repair_result["success"]:
148
+ result.update(repair_result)
149
+ result["repaired"] = True
150
+ return result
151
+ else:
152
+ result["errors"].extend(repair_result["errors"])
153
+
154
+ return result
155
+
156
+ @staticmethod
157
+ def _try_direct_json_parse(text: str) -> Optional[Dict[str, Any]]:
158
+ """Try to parse text directly as JSON"""
159
+ text = text.strip()
160
+ if not text:
161
+ return None
162
+ return json.loads(text)
163
+
164
+ @staticmethod
165
+ def _try_json_code_block(text: str) -> Optional[Dict[str, Any]]:
166
+ """Extract JSON from code blocks"""
167
+ patterns = [
168
+ r'```json\s*(.*?)\s*```',
169
+ r'```JSON\s*(.*?)\s*```',
170
+ r'```\s*(\{.*?\})\s*```'
171
+ ]
172
+
173
+ for pattern in patterns:
174
+ match = re.search(pattern, text, re.DOTALL | re.IGNORECASE)
175
+ if match:
176
+ json_str = match.group(1).strip()
177
+ if json_str:
178
+ return json.loads(json_str)
123
179
 
124
180
  return None
125
181
 
182
+ @staticmethod
183
+ def _try_first_json_object(text: str) -> Optional[Dict[str, Any]]:
184
+ """Find and parse the first JSON object in text"""
185
+ # Look for the first { and find its matching }
186
+ start_idx = text.find('{')
187
+ if start_idx == -1:
188
+ return None
189
+
190
+ brace_count = 0
191
+ in_string = False
192
+ escape_next = False
193
+
194
+ for i, char in enumerate(text[start_idx:], start_idx):
195
+ if escape_next:
196
+ escape_next = False
197
+ continue
198
+
199
+ if char == '\\':
200
+ escape_next = True
201
+ continue
202
+
203
+ if char == '"' and not escape_next:
204
+ in_string = not in_string
205
+ continue
206
+
207
+ if not in_string:
208
+ if char == '{':
209
+ brace_count += 1
210
+ elif char == '}':
211
+ brace_count -= 1
212
+ if brace_count == 0:
213
+ json_str = text[start_idx:i+1]
214
+ return json.loads(json_str)
215
+
216
+ return None
217
+
218
+ @staticmethod
219
+ def _try_between_braces(text: str) -> Optional[Dict[str, Any]]:
220
+ """Extract content between first { and last }"""
221
+ first_brace = text.find('{')
222
+ last_brace = text.rfind('}')
223
+
224
+ if first_brace != -1 and last_brace != -1 and last_brace > first_brace:
225
+ json_str = text[first_brace:last_brace+1]
226
+ return json.loads(json_str)
227
+
228
+ return None
229
+
230
+ @staticmethod
231
+ def _try_multiple_json_objects(text: str) -> Optional[List[Dict[str, Any]]]:
232
+ """Try to extract multiple JSON objects"""
233
+ objects = []
234
+ remaining_text = text
235
+
236
+ while True:
237
+ try:
238
+ obj = TextProcessor._try_first_json_object(remaining_text)
239
+ if obj is None:
240
+ break
241
+ objects.append(obj)
242
+
243
+ # Find where this object ends and continue
244
+ obj_str = json.dumps(obj)
245
+ obj_end = remaining_text.find('}')
246
+ if obj_end == -1:
247
+ break
248
+ remaining_text = remaining_text[obj_end+1:]
249
+
250
+ except:
251
+ break
252
+
253
+ return objects if objects else None
254
+
255
+ @staticmethod
256
+ def _try_yaml_like_parsing(text: str) -> Optional[Dict[str, Any]]:
257
+ """Try to parse YAML-like structures and convert to JSON"""
258
+ try:
259
+ # Simple YAML-like parsing for basic cases
260
+ lines = text.strip().split('\n')
261
+ result = {}
262
+
263
+ for line in lines:
264
+ line = line.strip()
265
+ if ':' in line and not line.startswith('#'):
266
+ key, value = line.split(':', 1)
267
+ key = key.strip().strip('"\'')
268
+ value = value.strip().strip('"\'')
269
+
270
+ # Try to convert value to appropriate type
271
+ if value.lower() in ['true', 'false']:
272
+ value = value.lower() == 'true'
273
+ elif value.isdigit():
274
+ value = int(value)
275
+ elif '.' in value and value.replace('.', '').isdigit():
276
+ value = float(value)
277
+
278
+ result[key] = value
279
+
280
+ return result if result else None
281
+ except:
282
+ return None
283
+
284
+ @staticmethod
285
+ def _validate_json_schema(data: Any, schema: Dict) -> Dict[str, Any]:
286
+ """Validate JSON data against a simple schema"""
287
+ try:
288
+ # Try jsonschema library first
289
+ try:
290
+ import jsonschema
291
+ jsonschema.validate(instance=data, schema=schema)
292
+ return {"valid": True, "error": None}
293
+ except ImportError:
294
+ # Fallback to basic validation
295
+ return TextProcessor._basic_schema_validation(data, schema)
296
+ except jsonschema.ValidationError as e:
297
+ return {"valid": False, "error": str(e)}
298
+
299
+ except Exception as e:
300
+ return {"valid": False, "error": f"Schema validation error: {str(e)}"}
301
+
302
+ @staticmethod
303
+ def _basic_schema_validation(data: Any, schema: Dict) -> Dict[str, Any]:
304
+ """Basic schema validation without jsonschema library"""
305
+ try:
306
+ if "type" in schema:
307
+ expected_type = schema["type"]
308
+ if expected_type == "object" and not isinstance(data, dict):
309
+ return {"valid": False, "error": f"Expected object, got {type(data).__name__}"}
310
+ elif expected_type == "array" and not isinstance(data, list):
311
+ return {"valid": False, "error": f"Expected array, got {type(data).__name__}"}
312
+ elif expected_type == "string" and not isinstance(data, str):
313
+ return {"valid": False, "error": f"Expected string, got {type(data).__name__}"}
314
+ elif expected_type == "number" and not isinstance(data, (int, float)):
315
+ return {"valid": False, "error": f"Expected number, got {type(data).__name__}"}
316
+ elif expected_type == "boolean" and not isinstance(data, bool):
317
+ return {"valid": False, "error": f"Expected boolean, got {type(data).__name__}"}
318
+
319
+ if "required" in schema and isinstance(data, dict):
320
+ for required_field in schema["required"]:
321
+ if required_field not in data:
322
+ return {"valid": False, "error": f"Missing required field: {required_field}"}
323
+
324
+ return {"valid": True, "error": None}
325
+ except Exception as e:
326
+ return {"valid": False, "error": f"Basic validation error: {str(e)}"}
327
+
328
+ @staticmethod
329
+ def _attempt_json_repair(text: str, schema: Optional[Dict], max_attempts: int) -> Dict[str, Any]:
330
+ """Attempt to repair malformed JSON"""
331
+ result = {"success": False, "data": None, "errors": []}
332
+
333
+ repair_strategies = [
334
+ TextProcessor._repair_missing_quotes,
335
+ TextProcessor._repair_trailing_commas,
336
+ TextProcessor._repair_unescaped_quotes,
337
+ TextProcessor._repair_incomplete_objects
338
+ ]
339
+
340
+ current_text = text
341
+
342
+ for attempt in range(max_attempts):
343
+ for strategy_name, repair_func in [
344
+ ("missing_quotes", TextProcessor._repair_missing_quotes),
345
+ ("trailing_commas", TextProcessor._repair_trailing_commas),
346
+ ("unescaped_quotes", TextProcessor._repair_unescaped_quotes),
347
+ ("incomplete_objects", TextProcessor._repair_incomplete_objects)
348
+ ]:
349
+ try:
350
+ repaired_text = repair_func(current_text)
351
+ if repaired_text != current_text:
352
+ # Try to parse the repaired text
353
+ try:
354
+ repaired_data = json.loads(repaired_text)
355
+
356
+ # Validate if schema provided
357
+ if schema:
358
+ validation = TextProcessor._validate_json_schema(repaired_data, schema)
359
+ if validation["valid"]:
360
+ result.update({
361
+ "success": True,
362
+ "data": repaired_data,
363
+ "method": f"repair_{strategy_name}"
364
+ })
365
+ return result
366
+ else:
367
+ result["errors"].append(f"repair_{strategy_name}: {validation['error']}")
368
+ else:
369
+ result.update({
370
+ "success": True,
371
+ "data": repaired_data,
372
+ "method": f"repair_{strategy_name}"
373
+ })
374
+ return result
375
+ except json.JSONDecodeError as e:
376
+ result["errors"].append(f"repair_{strategy_name}: Still invalid JSON after repair - {str(e)}")
377
+
378
+ current_text = repaired_text
379
+ except Exception as e:
380
+ result["errors"].append(f"repair_{strategy_name}: Repair attempt failed - {str(e)}")
381
+
382
+ return result
383
+
384
+ @staticmethod
385
+ def _repair_missing_quotes(text: str) -> str:
386
+ """Add quotes around unquoted keys"""
387
+ # Simple regex to add quotes around keys
388
+ pattern = r'(\s*)([a-zA-Z_][a-zA-Z0-9_]*)\s*:'
389
+ return re.sub(pattern, r'\1"\2":', text)
390
+
391
+ @staticmethod
392
+ def _repair_trailing_commas(text: str) -> str:
393
+ """Remove trailing commas"""
394
+ # Remove trailing commas before } or ]
395
+ text = re.sub(r',\s*([}\]])', r'\1', text)
396
+ return text
397
+
398
+ @staticmethod
399
+ def _repair_unescaped_quotes(text: str) -> str:
400
+ """Escape unescaped quotes in strings"""
401
+ # This is a simplified approach - in practice this is quite complex
402
+ # Replace unescaped quotes that are clearly inside string values
403
+ return text.replace('\\"', '"').replace('"', '\\"').replace('\\\\"', '\\"')
404
+
405
+ @staticmethod
406
+ def _repair_incomplete_objects(text: str) -> str:
407
+ """Try to complete incomplete JSON objects"""
408
+ text = text.strip()
409
+
410
+ # Add missing closing braces
411
+ open_braces = text.count('{')
412
+ close_braces = text.count('}')
413
+ if open_braces > close_braces:
414
+ text += '}' * (open_braces - close_braces)
415
+
416
+ # Add missing closing brackets
417
+ open_brackets = text.count('[')
418
+ close_brackets = text.count(']')
419
+ if open_brackets > close_brackets:
420
+ text += ']' * (open_brackets - close_brackets)
421
+
422
+ return text
423
+
126
424
  @staticmethod
127
425
  def split_into_sentences(text: str) -> List[str]:
128
426
  """将文本分割为句子"""