isa-model 0.3.5__py3-none-any.whl → 0.3.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- isa_model/__init__.py +30 -1
- isa_model/client.py +937 -0
- isa_model/core/config/__init__.py +16 -0
- isa_model/core/config/config_manager.py +514 -0
- isa_model/core/config.py +426 -0
- isa_model/core/models/model_billing_tracker.py +476 -0
- isa_model/core/models/model_manager.py +399 -0
- isa_model/core/{storage/supabase_storage.py → models/model_repo.py} +72 -73
- isa_model/core/pricing_manager.py +426 -0
- isa_model/core/services/__init__.py +19 -0
- isa_model/core/services/intelligent_model_selector.py +547 -0
- isa_model/core/types.py +291 -0
- isa_model/deployment/__init__.py +2 -0
- isa_model/deployment/cloud/modal/isa_vision_doc_service.py +157 -3
- isa_model/deployment/cloud/modal/isa_vision_table_service.py +532 -0
- isa_model/deployment/cloud/modal/isa_vision_ui_service.py +104 -3
- isa_model/deployment/cloud/modal/register_models.py +321 -0
- isa_model/deployment/runtime/deployed_service.py +338 -0
- isa_model/deployment/services/__init__.py +9 -0
- isa_model/deployment/services/auto_deploy_vision_service.py +538 -0
- isa_model/deployment/services/model_service.py +332 -0
- isa_model/deployment/services/service_monitor.py +356 -0
- isa_model/deployment/services/service_registry.py +527 -0
- isa_model/deployment/services/simple_auto_deploy_vision_service.py +275 -0
- isa_model/eval/__init__.py +80 -44
- isa_model/eval/config/__init__.py +10 -0
- isa_model/eval/config/evaluation_config.py +108 -0
- isa_model/eval/evaluators/__init__.py +18 -0
- isa_model/eval/evaluators/base_evaluator.py +503 -0
- isa_model/eval/evaluators/llm_evaluator.py +472 -0
- isa_model/eval/factory.py +417 -709
- isa_model/eval/infrastructure/__init__.py +24 -0
- isa_model/eval/infrastructure/experiment_tracker.py +466 -0
- isa_model/eval/metrics.py +191 -21
- isa_model/inference/ai_factory.py +257 -601
- isa_model/inference/services/audio/base_stt_service.py +65 -1
- isa_model/inference/services/audio/base_tts_service.py +75 -1
- isa_model/inference/services/audio/openai_stt_service.py +189 -151
- isa_model/inference/services/audio/openai_tts_service.py +12 -10
- isa_model/inference/services/audio/replicate_tts_service.py +61 -56
- isa_model/inference/services/base_service.py +55 -17
- isa_model/inference/services/embedding/base_embed_service.py +65 -1
- isa_model/inference/services/embedding/ollama_embed_service.py +103 -43
- isa_model/inference/services/embedding/openai_embed_service.py +8 -10
- isa_model/inference/services/helpers/stacked_config.py +148 -0
- isa_model/inference/services/img/__init__.py +18 -0
- isa_model/inference/services/{vision → img}/base_image_gen_service.py +80 -1
- isa_model/inference/services/{stacked → img}/flux_professional_service.py +25 -1
- isa_model/inference/services/{stacked → img/helpers}/base_stacked_service.py +40 -35
- isa_model/inference/services/{vision → img}/replicate_image_gen_service.py +44 -31
- isa_model/inference/services/llm/__init__.py +3 -3
- isa_model/inference/services/llm/base_llm_service.py +492 -40
- isa_model/inference/services/llm/helpers/llm_prompts.py +258 -0
- isa_model/inference/services/llm/helpers/llm_utils.py +280 -0
- isa_model/inference/services/llm/ollama_llm_service.py +51 -17
- isa_model/inference/services/llm/openai_llm_service.py +70 -19
- isa_model/inference/services/llm/yyds_llm_service.py +24 -23
- isa_model/inference/services/vision/__init__.py +38 -4
- isa_model/inference/services/vision/base_vision_service.py +218 -117
- isa_model/inference/services/vision/{isA_vision_service.py → disabled/isA_vision_service.py} +98 -0
- isa_model/inference/services/{stacked → vision}/doc_analysis_service.py +1 -1
- isa_model/inference/services/vision/helpers/base_stacked_service.py +274 -0
- isa_model/inference/services/vision/helpers/image_utils.py +272 -3
- isa_model/inference/services/vision/helpers/vision_prompts.py +297 -0
- isa_model/inference/services/vision/openai_vision_service.py +104 -307
- isa_model/inference/services/vision/replicate_vision_service.py +140 -325
- isa_model/inference/services/{stacked → vision}/ui_analysis_service.py +2 -498
- isa_model/scripts/register_models.py +370 -0
- isa_model/scripts/register_models_with_embeddings.py +510 -0
- isa_model/serving/api/fastapi_server.py +6 -1
- isa_model/serving/api/routes/unified.py +274 -0
- {isa_model-0.3.5.dist-info → isa_model-0.3.7.dist-info}/METADATA +4 -1
- {isa_model-0.3.5.dist-info → isa_model-0.3.7.dist-info}/RECORD +78 -53
- isa_model/config/__init__.py +0 -9
- isa_model/config/config_manager.py +0 -213
- isa_model/core/model_manager.py +0 -213
- isa_model/core/model_registry.py +0 -375
- isa_model/core/vision_models_init.py +0 -116
- isa_model/inference/billing_tracker.py +0 -406
- isa_model/inference/services/llm/triton_llm_service.py +0 -481
- isa_model/inference/services/stacked/__init__.py +0 -26
- isa_model/inference/services/stacked/config.py +0 -426
- isa_model/inference/services/vision/ollama_vision_service.py +0 -194
- /isa_model/core/{model_storage.py → models/model_storage.py} +0 -0
- /isa_model/inference/services/{vision → embedding}/helpers/text_splitter.py +0 -0
- /isa_model/inference/services/llm/{llm_adapter.py → helpers/llm_adapter.py} +0 -0
- {isa_model-0.3.5.dist-info → isa_model-0.3.7.dist-info}/WHEEL +0 -0
- {isa_model-0.3.5.dist-info → isa_model-0.3.7.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,148 @@
|
|
1
|
+
"""
|
2
|
+
Configuration system for stacked services
|
3
|
+
"""
|
4
|
+
|
5
|
+
from typing import Dict, Any, List, Optional
|
6
|
+
from dataclasses import dataclass, field
|
7
|
+
from enum import Enum
|
8
|
+
|
9
|
+
# Define stacked service specific layer types
|
10
|
+
class StackedLayerType(Enum):
|
11
|
+
"""Types of processing layers for stacked services"""
|
12
|
+
INTELLIGENCE = "intelligence" # High-level understanding
|
13
|
+
DETECTION = "detection" # Element/object detection
|
14
|
+
CLASSIFICATION = "classification" # Detailed classification
|
15
|
+
VALIDATION = "validation" # Result validation
|
16
|
+
TRANSFORMATION = "transformation" # Data transformation
|
17
|
+
GENERATION = "generation" # Content generation
|
18
|
+
ENHANCEMENT = "enhancement" # Quality enhancement
|
19
|
+
CONTROL = "control" # Precise control/refinement
|
20
|
+
UPSCALING = "upscaling" # Resolution enhancement
|
21
|
+
|
22
|
+
@dataclass
|
23
|
+
class LayerConfig:
|
24
|
+
"""Configuration for a processing layer"""
|
25
|
+
name: str
|
26
|
+
layer_type: StackedLayerType
|
27
|
+
service_type: str # e.g., 'vision', 'llm'
|
28
|
+
model_name: str
|
29
|
+
parameters: Dict[str, Any]
|
30
|
+
depends_on: List[str] # Layer dependencies
|
31
|
+
timeout: float = 30.0
|
32
|
+
retry_count: int = 1
|
33
|
+
fallback_enabled: bool = True
|
34
|
+
|
35
|
+
@dataclass
|
36
|
+
class LayerResult:
|
37
|
+
"""Result from a processing layer"""
|
38
|
+
layer_name: str
|
39
|
+
success: bool
|
40
|
+
data: Any
|
41
|
+
metadata: Dict[str, Any]
|
42
|
+
execution_time: float
|
43
|
+
error: Optional[str] = None
|
44
|
+
|
45
|
+
class WorkflowType(Enum):
|
46
|
+
"""Predefined workflow types"""
|
47
|
+
UI_ANALYSIS_FAST = "ui_analysis_fast"
|
48
|
+
UI_ANALYSIS_ACCURATE = "ui_analysis_accurate"
|
49
|
+
UI_ANALYSIS_COMPREHENSIVE = "ui_analysis_comprehensive"
|
50
|
+
SEARCH_PAGE_ANALYSIS = "search_page_analysis"
|
51
|
+
CONTENT_EXTRACTION = "content_extraction"
|
52
|
+
FORM_INTERACTION = "form_interaction"
|
53
|
+
NAVIGATION_ANALYSIS = "navigation_analysis"
|
54
|
+
CUSTOM = "custom"
|
55
|
+
|
56
|
+
@dataclass
|
57
|
+
class StackedServiceConfig:
|
58
|
+
"""Configuration for a stacked service workflow"""
|
59
|
+
name: str
|
60
|
+
workflow_type: WorkflowType
|
61
|
+
layers: List[LayerConfig] = field(default_factory=list)
|
62
|
+
global_timeout: float = 120.0
|
63
|
+
parallel_execution: bool = False
|
64
|
+
fail_fast: bool = False
|
65
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
66
|
+
|
67
|
+
class ConfigManager:
|
68
|
+
"""Manager for stacked service configurations"""
|
69
|
+
|
70
|
+
PREDEFINED_CONFIGS = {
|
71
|
+
WorkflowType.UI_ANALYSIS_FAST: {
|
72
|
+
"name": "Fast UI Analysis",
|
73
|
+
"layers": [
|
74
|
+
LayerConfig(
|
75
|
+
name="page_intelligence",
|
76
|
+
layer_type=StackedLayerType.INTELLIGENCE,
|
77
|
+
service_type="vision",
|
78
|
+
model_name="gpt-4.1-nano",
|
79
|
+
parameters={"max_tokens": 300},
|
80
|
+
depends_on=[],
|
81
|
+
timeout=10.0,
|
82
|
+
fallback_enabled=True
|
83
|
+
),
|
84
|
+
LayerConfig(
|
85
|
+
name="element_detection",
|
86
|
+
layer_type=StackedLayerType.DETECTION,
|
87
|
+
service_type="vision",
|
88
|
+
model_name="omniparser",
|
89
|
+
parameters={
|
90
|
+
"imgsz": 480,
|
91
|
+
"box_threshold": 0.08,
|
92
|
+
"iou_threshold": 0.2
|
93
|
+
},
|
94
|
+
depends_on=["page_intelligence"],
|
95
|
+
timeout=15.0,
|
96
|
+
fallback_enabled=True
|
97
|
+
),
|
98
|
+
LayerConfig(
|
99
|
+
name="element_classification",
|
100
|
+
layer_type=StackedLayerType.CLASSIFICATION,
|
101
|
+
service_type="vision",
|
102
|
+
model_name="gpt-4.1-nano",
|
103
|
+
parameters={"max_tokens": 200},
|
104
|
+
depends_on=["page_intelligence", "element_detection"],
|
105
|
+
timeout=20.0,
|
106
|
+
fallback_enabled=False
|
107
|
+
)
|
108
|
+
],
|
109
|
+
"global_timeout": 60.0,
|
110
|
+
"parallel_execution": False,
|
111
|
+
"fail_fast": False,
|
112
|
+
"metadata": {
|
113
|
+
"description": "Fast UI analysis optimized for speed",
|
114
|
+
"expected_time": "30-45 seconds",
|
115
|
+
"accuracy": "medium"
|
116
|
+
}
|
117
|
+
}
|
118
|
+
}
|
119
|
+
|
120
|
+
@classmethod
|
121
|
+
def get_config(cls, workflow_type: WorkflowType) -> StackedServiceConfig:
|
122
|
+
"""Get predefined configuration for a workflow type"""
|
123
|
+
if workflow_type not in cls.PREDEFINED_CONFIGS:
|
124
|
+
raise ValueError(f"Unknown workflow type: {workflow_type}")
|
125
|
+
|
126
|
+
config_data = cls.PREDEFINED_CONFIGS[workflow_type]
|
127
|
+
|
128
|
+
return StackedServiceConfig(
|
129
|
+
name=config_data["name"],
|
130
|
+
workflow_type=workflow_type,
|
131
|
+
layers=config_data["layers"],
|
132
|
+
global_timeout=config_data["global_timeout"],
|
133
|
+
parallel_execution=config_data["parallel_execution"],
|
134
|
+
fail_fast=config_data["fail_fast"],
|
135
|
+
metadata=config_data["metadata"]
|
136
|
+
)
|
137
|
+
|
138
|
+
# Convenience function for quick access
|
139
|
+
def get_ui_analysis_config(speed: str = "accurate") -> StackedServiceConfig:
|
140
|
+
"""Get UI analysis configuration by speed preference"""
|
141
|
+
speed_mapping = {
|
142
|
+
"fast": WorkflowType.UI_ANALYSIS_FAST,
|
143
|
+
"accurate": WorkflowType.UI_ANALYSIS_ACCURATE,
|
144
|
+
"comprehensive": WorkflowType.UI_ANALYSIS_COMPREHENSIVE
|
145
|
+
}
|
146
|
+
|
147
|
+
workflow_type = speed_mapping.get(speed.lower(), WorkflowType.UI_ANALYSIS_ACCURATE)
|
148
|
+
return ConfigManager.get_config(workflow_type)
|
@@ -0,0 +1,18 @@
|
|
1
|
+
"""
|
2
|
+
Image Generation Services
|
3
|
+
|
4
|
+
This module contains services for image generation, separate from vision understanding.
|
5
|
+
Including stacked services for complex image generation pipelines.
|
6
|
+
"""
|
7
|
+
|
8
|
+
from .base_image_gen_service import BaseImageGenService
|
9
|
+
from .replicate_image_gen_service import ReplicateImageGenService
|
10
|
+
|
11
|
+
# Stacked Image Generation Services
|
12
|
+
from .flux_professional_service import FluxProfessionalService
|
13
|
+
|
14
|
+
__all__ = [
|
15
|
+
'BaseImageGenService',
|
16
|
+
'ReplicateImageGenService',
|
17
|
+
'FluxProfessionalService'
|
18
|
+
]
|
@@ -3,7 +3,86 @@ from typing import Dict, Any, List, Union, Optional, BinaryIO
|
|
3
3
|
from isa_model.inference.services.base_service import BaseService
|
4
4
|
|
5
5
|
class BaseImageGenService(BaseService):
|
6
|
-
"""Base class for image generation services"""
|
6
|
+
"""Base class for image generation services with unified task dispatch"""
|
7
|
+
|
8
|
+
async def invoke(
|
9
|
+
self,
|
10
|
+
prompt: str,
|
11
|
+
task: Optional[str] = None,
|
12
|
+
**kwargs
|
13
|
+
) -> Union[Dict[str, Any], List[Dict[str, Any]]]:
|
14
|
+
"""
|
15
|
+
统一的任务分发方法 - Base类提供通用实现
|
16
|
+
|
17
|
+
Args:
|
18
|
+
prompt: 文本提示词
|
19
|
+
task: 任务类型,支持多种图像生成任务
|
20
|
+
**kwargs: 任务特定的附加参数
|
21
|
+
|
22
|
+
Returns:
|
23
|
+
Dict or List[Dict] containing generation results
|
24
|
+
"""
|
25
|
+
task = task or "generate"
|
26
|
+
|
27
|
+
# ==================== 图像生成类任务 ====================
|
28
|
+
if task == "generate":
|
29
|
+
num_images = kwargs.get("num_images", 1)
|
30
|
+
if num_images == 1:
|
31
|
+
return await self.generate_image(
|
32
|
+
prompt,
|
33
|
+
kwargs.get("negative_prompt"),
|
34
|
+
kwargs.get("width", 512),
|
35
|
+
kwargs.get("height", 512),
|
36
|
+
kwargs.get("num_inference_steps", 20),
|
37
|
+
kwargs.get("guidance_scale", 7.5),
|
38
|
+
kwargs.get("seed")
|
39
|
+
)
|
40
|
+
else:
|
41
|
+
return await self.generate_images(
|
42
|
+
prompt,
|
43
|
+
num_images,
|
44
|
+
kwargs.get("negative_prompt"),
|
45
|
+
kwargs.get("width", 512),
|
46
|
+
kwargs.get("height", 512),
|
47
|
+
kwargs.get("num_inference_steps", 20),
|
48
|
+
kwargs.get("guidance_scale", 7.5),
|
49
|
+
kwargs.get("seed")
|
50
|
+
)
|
51
|
+
elif task == "generate_batch":
|
52
|
+
return await self.generate_images(
|
53
|
+
prompt,
|
54
|
+
kwargs.get("num_images", 4),
|
55
|
+
kwargs.get("negative_prompt"),
|
56
|
+
kwargs.get("width", 512),
|
57
|
+
kwargs.get("height", 512),
|
58
|
+
kwargs.get("num_inference_steps", 20),
|
59
|
+
kwargs.get("guidance_scale", 7.5),
|
60
|
+
kwargs.get("seed")
|
61
|
+
)
|
62
|
+
elif task == "img2img":
|
63
|
+
init_image = kwargs.get("init_image")
|
64
|
+
if not init_image:
|
65
|
+
raise ValueError("img2img task requires init_image parameter")
|
66
|
+
return await self.image_to_image(
|
67
|
+
prompt,
|
68
|
+
init_image,
|
69
|
+
kwargs.get("strength", 0.8),
|
70
|
+
kwargs.get("negative_prompt"),
|
71
|
+
kwargs.get("num_inference_steps", 20),
|
72
|
+
kwargs.get("guidance_scale", 7.5),
|
73
|
+
kwargs.get("seed")
|
74
|
+
)
|
75
|
+
else:
|
76
|
+
raise NotImplementedError(f"{self.__class__.__name__} does not support task: {task}")
|
77
|
+
|
78
|
+
def get_supported_tasks(self) -> List[str]:
|
79
|
+
"""
|
80
|
+
获取支持的任务列表
|
81
|
+
|
82
|
+
Returns:
|
83
|
+
List of supported task names
|
84
|
+
"""
|
85
|
+
return ["generate", "generate_batch", "img2img"]
|
7
86
|
|
8
87
|
@abstractmethod
|
9
88
|
async def generate_image(
|
@@ -10,7 +10,7 @@ import io
|
|
10
10
|
from typing import Dict, Any, List, Optional
|
11
11
|
from PIL import Image
|
12
12
|
|
13
|
-
from .base_stacked_service import BaseStackedService, LayerConfig, LayerType, LayerResult
|
13
|
+
from .helpers.base_stacked_service import BaseStackedService, LayerConfig, LayerType, LayerResult
|
14
14
|
|
15
15
|
logger = logging.getLogger(__name__)
|
16
16
|
|
@@ -571,6 +571,30 @@ class FluxProfessionalService(BaseStackedService):
|
|
571
571
|
|
572
572
|
return None
|
573
573
|
|
574
|
+
def generate_final_output(self, results: Dict[str, LayerResult]) -> Any:
|
575
|
+
"""Generate final output from all layer results"""
|
576
|
+
# Get the best available result
|
577
|
+
final_result = None
|
578
|
+
for layer_name in ["ultimate_upscaling", "detail_enhancement", "lora_style_application", "controlnet_refinement", "flux_base_generation"]:
|
579
|
+
if layer_name in results and results[layer_name].success:
|
580
|
+
final_result = results[layer_name]
|
581
|
+
break
|
582
|
+
|
583
|
+
if final_result:
|
584
|
+
return {
|
585
|
+
"success": True,
|
586
|
+
"final_image": final_result.data,
|
587
|
+
"pipeline_stages": list(results.keys()),
|
588
|
+
"successful_stages": [name for name, result in results.items() if result.success]
|
589
|
+
}
|
590
|
+
else:
|
591
|
+
return {
|
592
|
+
"success": False,
|
593
|
+
"error": "No successful pipeline stages",
|
594
|
+
"pipeline_stages": list(results.keys()),
|
595
|
+
"failed_stages": [name for name, result in results.items() if not result.success]
|
596
|
+
}
|
597
|
+
|
574
598
|
async def close(self):
|
575
599
|
"""Clean up services"""
|
576
600
|
for service in self.services.values():
|
@@ -10,42 +10,47 @@ import logging
|
|
10
10
|
from dataclasses import dataclass
|
11
11
|
from enum import Enum
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
13
|
+
# Import shared types from helpers
|
14
|
+
try:
|
15
|
+
from ..helpers.stacked_config import StackedLayerType as LayerType, LayerConfig, LayerResult
|
16
|
+
except ImportError:
|
17
|
+
# Fallback definitions if shared config is not available
|
18
|
+
class LayerType(Enum):
|
19
|
+
"""Types of processing layers"""
|
20
|
+
INTELLIGENCE = "intelligence"
|
21
|
+
DETECTION = "detection"
|
22
|
+
CLASSIFICATION = "classification"
|
23
|
+
VALIDATION = "validation"
|
24
|
+
TRANSFORMATION = "transformation"
|
25
|
+
GENERATION = "generation"
|
26
|
+
ENHANCEMENT = "enhancement"
|
27
|
+
CONTROL = "control"
|
28
|
+
UPSCALING = "upscaling"
|
29
|
+
|
30
|
+
@dataclass
|
31
|
+
class LayerConfig:
|
32
|
+
"""Configuration for a processing layer"""
|
33
|
+
name: str
|
34
|
+
layer_type: LayerType
|
35
|
+
service_type: str
|
36
|
+
model_name: str
|
37
|
+
parameters: Dict[str, Any]
|
38
|
+
depends_on: List[str]
|
39
|
+
timeout: float = 30.0
|
40
|
+
retry_count: int = 1
|
41
|
+
fallback_enabled: bool = True
|
42
|
+
|
43
|
+
@dataclass
|
44
|
+
class LayerResult:
|
45
|
+
"""Result from a processing layer"""
|
46
|
+
layer_name: str
|
47
|
+
success: bool
|
48
|
+
data: Any
|
49
|
+
metadata: Dict[str, Any]
|
50
|
+
execution_time: float
|
51
|
+
error: Optional[str] = None
|
39
52
|
|
40
|
-
|
41
|
-
class LayerResult:
|
42
|
-
"""Result from a processing layer"""
|
43
|
-
layer_name: str
|
44
|
-
success: bool
|
45
|
-
data: Any
|
46
|
-
metadata: Dict[str, Any]
|
47
|
-
execution_time: float
|
48
|
-
error: Optional[str] = None
|
53
|
+
logger = logging.getLogger(__name__)
|
49
54
|
|
50
55
|
class BaseStackedService(ABC):
|
51
56
|
"""
|
@@ -17,38 +17,41 @@ import replicate
|
|
17
17
|
from PIL import Image
|
18
18
|
from io import BytesIO
|
19
19
|
|
20
|
-
from
|
21
|
-
from isa_model.inference.providers.base_provider import BaseProvider
|
20
|
+
from .base_image_gen_service import BaseImageGenService
|
22
21
|
|
23
|
-
# 设置日志记录
|
24
|
-
logging.basicConfig(level=logging.INFO)
|
25
22
|
logger = logging.getLogger(__name__)
|
26
23
|
|
27
24
|
class ReplicateImageGenService(BaseImageGenService):
|
28
25
|
"""
|
29
|
-
Replicate 图像生成服务
|
26
|
+
Replicate 图像生成服务 with unified architecture
|
30
27
|
- flux-schnell: 文生图 (t2i) - $3 per 1000 images
|
31
28
|
- flux-kontext-pro: 图生图 (i2i) - $0.04 per image
|
32
29
|
"""
|
33
30
|
|
34
|
-
def __init__(self,
|
35
|
-
super().__init__(
|
31
|
+
def __init__(self, provider_name: str, model_name: str, **kwargs):
|
32
|
+
super().__init__(provider_name, model_name, **kwargs)
|
36
33
|
|
37
|
-
#
|
38
|
-
provider_config =
|
39
|
-
self.api_token = provider_config.get("api_token") or provider_config.get("replicate_api_token")
|
34
|
+
# Get configuration from centralized config manager
|
35
|
+
provider_config = self.get_provider_config()
|
40
36
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
37
|
+
try:
|
38
|
+
self.api_token = provider_config.get("api_key") or provider_config.get("replicate_api_token")
|
39
|
+
|
40
|
+
if not self.api_token:
|
41
|
+
raise ValueError("Replicate API token not found in provider configuration")
|
42
|
+
|
43
|
+
# Set API token
|
44
|
+
os.environ["REPLICATE_API_TOKEN"] = self.api_token
|
45
|
+
|
46
|
+
# Statistics
|
47
|
+
self.last_generation_count = 0
|
48
|
+
self.total_generation_count = 0
|
49
|
+
|
50
|
+
logger.info(f"Initialized ReplicateImageGenService with model '{self.model_name}'")
|
51
|
+
|
52
|
+
except Exception as e:
|
53
|
+
logger.error(f"Failed to initialize Replicate client: {e}")
|
54
|
+
raise ValueError(f"Failed to initialize Replicate client: {e}") from e
|
52
55
|
|
53
56
|
async def generate_image(
|
54
57
|
self,
|
@@ -313,25 +316,35 @@ class ReplicateImageGenService(BaseImageGenService):
|
|
313
316
|
# 计算成本
|
314
317
|
cost = self._calculate_cost(len(urls))
|
315
318
|
|
316
|
-
#
|
317
|
-
|
318
|
-
|
319
|
-
service_type=ServiceType.IMAGE_GENERATION,
|
319
|
+
# Track billing information
|
320
|
+
await self._track_usage(
|
321
|
+
service_type="image_generation",
|
320
322
|
operation="image_generation",
|
321
|
-
|
323
|
+
input_tokens=0,
|
324
|
+
output_tokens=0,
|
325
|
+
input_units=1, # Input prompt
|
326
|
+
output_units=len(urls), # Generated images count
|
322
327
|
metadata={
|
323
328
|
"model": self.model_name,
|
324
|
-
"prompt": input_data.get("prompt", "")[:100], #
|
325
|
-
"generation_type": "t2i" if "flux-schnell" in self.model_name else "i2i"
|
329
|
+
"prompt": input_data.get("prompt", "")[:100], # Truncate to 100 chars
|
330
|
+
"generation_type": "t2i" if "flux-schnell" in self.model_name else "i2i",
|
331
|
+
"image_count": len(urls),
|
332
|
+
"cost_usd": cost
|
326
333
|
}
|
327
334
|
)
|
328
335
|
|
336
|
+
# Return URLs instead of binary data for HTTP API compatibility
|
329
337
|
result = {
|
330
|
-
"urls": urls,
|
338
|
+
"urls": urls, # Image URLs - primary response
|
339
|
+
"url": urls[0] if urls else None, # First URL for convenience
|
340
|
+
"format": "jpg", # Default format
|
341
|
+
"width": input_data.get("width", 1024),
|
342
|
+
"height": input_data.get("height", 1024),
|
343
|
+
"seed": input_data.get("seed"),
|
331
344
|
"count": len(urls),
|
332
345
|
"cost_usd": cost,
|
333
|
-
"model": self.model_name,
|
334
346
|
"metadata": {
|
347
|
+
"model": self.model_name,
|
335
348
|
"input": input_data,
|
336
349
|
"generation_count": len(urls)
|
337
350
|
}
|
@@ -346,7 +359,7 @@ class ReplicateImageGenService(BaseImageGenService):
|
|
346
359
|
|
347
360
|
def _calculate_cost(self, image_count: int) -> float:
|
348
361
|
"""计算生成成本"""
|
349
|
-
from isa_model.core.model_manager import ModelManager
|
362
|
+
from isa_model.core.models.model_manager import ModelManager
|
350
363
|
|
351
364
|
manager = ModelManager()
|
352
365
|
|
@@ -5,10 +5,10 @@ LLM Services - Business logic services for Language Models
|
|
5
5
|
# Import LLM services here when created
|
6
6
|
from .ollama_llm_service import OllamaLLMService
|
7
7
|
from .openai_llm_service import OpenAILLMService
|
8
|
-
from .
|
8
|
+
from .yyds_llm_service import YydsLLMService
|
9
9
|
|
10
10
|
__all__ = [
|
11
11
|
"OllamaLLMService",
|
12
|
-
"OpenAILLMService",
|
13
|
-
"
|
12
|
+
"OpenAILLMService",
|
13
|
+
"YydsLLMService"
|
14
14
|
]
|