isage-middleware 0.2.4.3__cp311-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.
- isage_middleware-0.2.4.3.dist-info/METADATA +266 -0
- isage_middleware-0.2.4.3.dist-info/RECORD +94 -0
- isage_middleware-0.2.4.3.dist-info/WHEEL +5 -0
- isage_middleware-0.2.4.3.dist-info/top_level.txt +1 -0
- sage/middleware/__init__.py +59 -0
- sage/middleware/_version.py +6 -0
- sage/middleware/components/__init__.py +30 -0
- sage/middleware/components/extensions_compat.py +141 -0
- sage/middleware/components/sage_db/__init__.py +116 -0
- sage/middleware/components/sage_db/backend.py +136 -0
- sage/middleware/components/sage_db/service.py +15 -0
- sage/middleware/components/sage_flow/__init__.py +76 -0
- sage/middleware/components/sage_flow/python/__init__.py +14 -0
- sage/middleware/components/sage_flow/python/micro_service/__init__.py +4 -0
- sage/middleware/components/sage_flow/python/micro_service/sage_flow_service.py +88 -0
- sage/middleware/components/sage_flow/python/sage_flow.py +30 -0
- sage/middleware/components/sage_flow/service.py +14 -0
- sage/middleware/components/sage_mem/__init__.py +83 -0
- sage/middleware/components/sage_sias/__init__.py +59 -0
- sage/middleware/components/sage_sias/continual_learner.py +184 -0
- sage/middleware/components/sage_sias/coreset_selector.py +302 -0
- sage/middleware/components/sage_sias/types.py +94 -0
- sage/middleware/components/sage_tsdb/__init__.py +81 -0
- sage/middleware/components/sage_tsdb/python/__init__.py +21 -0
- sage/middleware/components/sage_tsdb/python/_sage_tsdb.pyi +17 -0
- sage/middleware/components/sage_tsdb/python/algorithms/__init__.py +17 -0
- sage/middleware/components/sage_tsdb/python/algorithms/base.py +51 -0
- sage/middleware/components/sage_tsdb/python/algorithms/out_of_order_join.py +248 -0
- sage/middleware/components/sage_tsdb/python/algorithms/window_aggregator.py +296 -0
- sage/middleware/components/sage_tsdb/python/micro_service/__init__.py +7 -0
- sage/middleware/components/sage_tsdb/python/micro_service/sage_tsdb_service.py +365 -0
- sage/middleware/components/sage_tsdb/python/sage_tsdb.py +523 -0
- sage/middleware/components/sage_tsdb/service.py +17 -0
- sage/middleware/components/vector_stores/__init__.py +25 -0
- sage/middleware/components/vector_stores/chroma.py +483 -0
- sage/middleware/components/vector_stores/chroma_adapter.py +185 -0
- sage/middleware/components/vector_stores/milvus.py +677 -0
- sage/middleware/operators/__init__.py +56 -0
- sage/middleware/operators/agent/__init__.py +24 -0
- sage/middleware/operators/agent/planning/__init__.py +5 -0
- sage/middleware/operators/agent/planning/llm_adapter.py +41 -0
- sage/middleware/operators/agent/planning/planner_adapter.py +98 -0
- sage/middleware/operators/agent/planning/router.py +107 -0
- sage/middleware/operators/agent/runtime.py +296 -0
- sage/middleware/operators/agentic/__init__.py +41 -0
- sage/middleware/operators/agentic/config.py +254 -0
- sage/middleware/operators/agentic/planning_operator.py +125 -0
- sage/middleware/operators/agentic/refined_searcher.py +132 -0
- sage/middleware/operators/agentic/runtime.py +241 -0
- sage/middleware/operators/agentic/timing_operator.py +125 -0
- sage/middleware/operators/agentic/tool_selection_operator.py +127 -0
- sage/middleware/operators/context/__init__.py +17 -0
- sage/middleware/operators/context/critic_evaluation.py +16 -0
- sage/middleware/operators/context/model_context.py +565 -0
- sage/middleware/operators/context/quality_label.py +12 -0
- sage/middleware/operators/context/search_query_results.py +61 -0
- sage/middleware/operators/context/search_result.py +42 -0
- sage/middleware/operators/context/search_session.py +79 -0
- sage/middleware/operators/filters/__init__.py +26 -0
- sage/middleware/operators/filters/context_sink.py +387 -0
- sage/middleware/operators/filters/context_source.py +376 -0
- sage/middleware/operators/filters/evaluate_filter.py +83 -0
- sage/middleware/operators/filters/tool_filter.py +74 -0
- sage/middleware/operators/llm/__init__.py +18 -0
- sage/middleware/operators/llm/sagellm_generator.py +432 -0
- sage/middleware/operators/rag/__init__.py +147 -0
- sage/middleware/operators/rag/arxiv.py +331 -0
- sage/middleware/operators/rag/chunk.py +13 -0
- sage/middleware/operators/rag/document_loaders.py +23 -0
- sage/middleware/operators/rag/evaluate.py +658 -0
- sage/middleware/operators/rag/generator.py +340 -0
- sage/middleware/operators/rag/index_builder/__init__.py +48 -0
- sage/middleware/operators/rag/index_builder/builder.py +363 -0
- sage/middleware/operators/rag/index_builder/manifest.py +101 -0
- sage/middleware/operators/rag/index_builder/storage.py +131 -0
- sage/middleware/operators/rag/pipeline.py +46 -0
- sage/middleware/operators/rag/profiler.py +59 -0
- sage/middleware/operators/rag/promptor.py +400 -0
- sage/middleware/operators/rag/refiner.py +231 -0
- sage/middleware/operators/rag/reranker.py +364 -0
- sage/middleware/operators/rag/retriever.py +1308 -0
- sage/middleware/operators/rag/searcher.py +37 -0
- sage/middleware/operators/rag/types.py +28 -0
- sage/middleware/operators/rag/writer.py +80 -0
- sage/middleware/operators/tools/__init__.py +71 -0
- sage/middleware/operators/tools/arxiv_paper_searcher.py +175 -0
- sage/middleware/operators/tools/arxiv_searcher.py +102 -0
- sage/middleware/operators/tools/duckduckgo_searcher.py +105 -0
- sage/middleware/operators/tools/image_captioner.py +104 -0
- sage/middleware/operators/tools/nature_news_fetcher.py +224 -0
- sage/middleware/operators/tools/searcher_tool.py +514 -0
- sage/middleware/operators/tools/text_detector.py +185 -0
- sage/middleware/operators/tools/url_text_extractor.py +104 -0
- sage/middleware/py.typed +2 -0
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import warnings
|
|
4
|
+
from importlib import import_module
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from sage_libs.sage_agentic.agents.action.mcp_registry import MCPRegistry
|
|
8
|
+
from sage_libs.sage_agentic.agents.profile.profile import BaseProfile
|
|
9
|
+
|
|
10
|
+
from sage.common.core.functions import MapFunction as MapOperator
|
|
11
|
+
from sage.middleware.operators.agent.runtime import AgentRuntime
|
|
12
|
+
from sage.middleware.operators.rag.generator import HFGenerator, OpenAIGenerator
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _maybe_instantiate(spec: dict[str, Any]):
|
|
16
|
+
module_path = spec["module"]
|
|
17
|
+
class_name = spec["class"]
|
|
18
|
+
kwargs = spec.get("init_kwargs", {})
|
|
19
|
+
module = import_module(module_path)
|
|
20
|
+
ctor = getattr(module, class_name)
|
|
21
|
+
return ctor(**kwargs) if kwargs else ctor()
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _build_generator(config: Any, engine_type: str = "sagellm"):
|
|
25
|
+
"""构建 LLM 生成器
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
config: 生成器配置,可以是已实例化的对象、模块路径配置或参数字典
|
|
29
|
+
engine_type: 引擎类型,支持 "sagellm"(默认)/ "openai" / "hf"
|
|
30
|
+
注意: "vllm" 已废弃,会自动转换为 sagellm 并发出警告
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
生成器实例
|
|
34
|
+
"""
|
|
35
|
+
if not config:
|
|
36
|
+
raise ValueError("generator config/object is required for AgentRuntimeOperator")
|
|
37
|
+
|
|
38
|
+
# 如果已经是生成器实例,直接返回
|
|
39
|
+
if hasattr(config, "execute") or hasattr(config, "generate"):
|
|
40
|
+
return config
|
|
41
|
+
|
|
42
|
+
# 模块路径方式实例化
|
|
43
|
+
if isinstance(config, dict) and "module" in config and "class" in config:
|
|
44
|
+
return _maybe_instantiate(config)
|
|
45
|
+
|
|
46
|
+
# 从配置中获取 engine_type(如果存在),覆盖参数
|
|
47
|
+
if isinstance(config, dict):
|
|
48
|
+
engine_type = config.get("engine_type", engine_type)
|
|
49
|
+
|
|
50
|
+
# 根据 engine_type 选择生成器
|
|
51
|
+
if engine_type == "vllm":
|
|
52
|
+
# vllm 已废弃,自动转换为 sagellm
|
|
53
|
+
warnings.warn(
|
|
54
|
+
"engine_type='vllm' is deprecated for agent generators. "
|
|
55
|
+
"Automatically using engine_type='sagellm' instead. "
|
|
56
|
+
"Please update your configuration.",
|
|
57
|
+
DeprecationWarning,
|
|
58
|
+
stacklevel=3,
|
|
59
|
+
)
|
|
60
|
+
engine_type = "sagellm" # 转换为 sagellm
|
|
61
|
+
|
|
62
|
+
if engine_type == "sagellm":
|
|
63
|
+
# 默认使用 sagellm
|
|
64
|
+
from sage.middleware.operators.llm import SageLLMGenerator
|
|
65
|
+
|
|
66
|
+
if isinstance(config, dict):
|
|
67
|
+
return SageLLMGenerator(
|
|
68
|
+
backend_type=config.get("backend_type", "auto"),
|
|
69
|
+
model_path=config.get("model_path", ""),
|
|
70
|
+
device_map=config.get("device_map", "auto"),
|
|
71
|
+
dtype=config.get("dtype", "auto"),
|
|
72
|
+
max_tokens=config.get("max_tokens", 2048),
|
|
73
|
+
temperature=config.get("temperature", 0.7),
|
|
74
|
+
top_p=config.get("top_p", 0.95),
|
|
75
|
+
top_k=config.get("top_k", 50),
|
|
76
|
+
timeout=config.get("timeout", 120.0),
|
|
77
|
+
default_options=config.get("default_options", {}),
|
|
78
|
+
)
|
|
79
|
+
return SageLLMGenerator()
|
|
80
|
+
|
|
81
|
+
elif engine_type in ("openai", "openai-compatible"):
|
|
82
|
+
return OpenAIGenerator(config if isinstance(config, dict) else {})
|
|
83
|
+
|
|
84
|
+
elif engine_type in ("hf", "huggingface"):
|
|
85
|
+
return HFGenerator(config if isinstance(config, dict) else {})
|
|
86
|
+
|
|
87
|
+
else:
|
|
88
|
+
# 兼容旧版 method 参数
|
|
89
|
+
method = ""
|
|
90
|
+
if isinstance(config, dict):
|
|
91
|
+
method = (config.get("method") or config.get("type") or "").lower()
|
|
92
|
+
|
|
93
|
+
if method.startswith("hf") or method.startswith("huggingface"):
|
|
94
|
+
return HFGenerator(config)
|
|
95
|
+
return OpenAIGenerator(config)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
from sage.middleware.operators.agent.planning.router import PlannerRouter
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def _build_planner(config: Any, generator):
|
|
102
|
+
if hasattr(config, "plan"):
|
|
103
|
+
return config
|
|
104
|
+
# planner_conf = config or {}
|
|
105
|
+
|
|
106
|
+
# Use PlannerRouter instead of direct LLMPlanner
|
|
107
|
+
return PlannerRouter(generator=generator)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _build_profile(config: Any) -> BaseProfile:
|
|
111
|
+
if isinstance(config, BaseProfile):
|
|
112
|
+
return config
|
|
113
|
+
if isinstance(config, dict) and "module" in config and "class" in config:
|
|
114
|
+
profile_obj = _maybe_instantiate(config)
|
|
115
|
+
if isinstance(profile_obj, BaseProfile):
|
|
116
|
+
return profile_obj
|
|
117
|
+
return BaseProfile.from_dict(config or {})
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def _build_tools(config: Any) -> MCPRegistry:
|
|
121
|
+
if isinstance(config, MCPRegistry):
|
|
122
|
+
return config
|
|
123
|
+
registry = MCPRegistry()
|
|
124
|
+
specs: list[Any]
|
|
125
|
+
if isinstance(config, dict):
|
|
126
|
+
specs = [config]
|
|
127
|
+
elif isinstance(config, list):
|
|
128
|
+
specs = config
|
|
129
|
+
else:
|
|
130
|
+
specs = []
|
|
131
|
+
|
|
132
|
+
for spec in specs:
|
|
133
|
+
if isinstance(spec, dict) and "module" in spec and "class" in spec:
|
|
134
|
+
tool = _maybe_instantiate(spec)
|
|
135
|
+
registry.register(tool)
|
|
136
|
+
elif hasattr(spec, "call") and hasattr(spec, "name"):
|
|
137
|
+
registry.register(spec)
|
|
138
|
+
else:
|
|
139
|
+
raise ValueError(f"Unsupported tool spec: {spec}")
|
|
140
|
+
return registry
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class AgentRuntimeOperator(MapOperator):
|
|
144
|
+
"""Wrap AgentRuntime into an L4 operator for drag-and-drop Studio workflows.
|
|
145
|
+
|
|
146
|
+
Supports engine_type switching:
|
|
147
|
+
- sagellm (default): Use SageLLMGenerator with configurable backend
|
|
148
|
+
- openai: Use OpenAIGenerator for OpenAI-compatible APIs
|
|
149
|
+
- hf: Use HFGenerator for HuggingFace models
|
|
150
|
+
|
|
151
|
+
Backend types for sagellm:
|
|
152
|
+
- auto (default): Automatically select best available backend
|
|
153
|
+
- mock: Mock backend for testing without GPU
|
|
154
|
+
- cuda: NVIDIA CUDA backend
|
|
155
|
+
- ascend: Huawei Ascend NPU backend
|
|
156
|
+
|
|
157
|
+
Example:
|
|
158
|
+
```python
|
|
159
|
+
# Using sagellm with auto backend (default)
|
|
160
|
+
operator = AgentRuntimeOperator(config={
|
|
161
|
+
"generator": {
|
|
162
|
+
"engine_type": "sagellm",
|
|
163
|
+
"backend_type": "auto",
|
|
164
|
+
"model_path": "Qwen/Qwen2.5-7B-Instruct",
|
|
165
|
+
},
|
|
166
|
+
"profile": {"name": "MyAgent"},
|
|
167
|
+
"tools": [],
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
# Using sagellm with mock backend (for testing)
|
|
171
|
+
operator = AgentRuntimeOperator(config={
|
|
172
|
+
"generator": {
|
|
173
|
+
"engine_type": "sagellm",
|
|
174
|
+
"backend_type": "mock",
|
|
175
|
+
},
|
|
176
|
+
"profile": {"name": "TestBot"},
|
|
177
|
+
"tools": [],
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
# Using OpenAI
|
|
181
|
+
operator = AgentRuntimeOperator(config={
|
|
182
|
+
"generator": {
|
|
183
|
+
"engine_type": "openai",
|
|
184
|
+
"model_name": "gpt-4o-mini",
|
|
185
|
+
"api_key": "sk-xxx", # pragma: allowlist secret
|
|
186
|
+
},
|
|
187
|
+
"profile": {"name": "MyAgent"},
|
|
188
|
+
"tools": [],
|
|
189
|
+
})
|
|
190
|
+
```
|
|
191
|
+
"""
|
|
192
|
+
|
|
193
|
+
def __init__(
|
|
194
|
+
self, config: dict[str, Any] | None = None, enable_profile: bool = False, **kwargs
|
|
195
|
+
):
|
|
196
|
+
super().__init__(**kwargs)
|
|
197
|
+
self.enable_profile = enable_profile
|
|
198
|
+
self.config = config or {}
|
|
199
|
+
|
|
200
|
+
profile_conf = self.config.get("profile", {})
|
|
201
|
+
generator_conf = self.config.get("generator")
|
|
202
|
+
planner_conf = self.config.get("planner", {})
|
|
203
|
+
tools_conf = self.config.get("tools", [])
|
|
204
|
+
runtime_conf = self.config.get("runtime", {})
|
|
205
|
+
|
|
206
|
+
# 获取 engine_type(优先从 generator 配置,其次从顶层配置)
|
|
207
|
+
engine_type = "sagellm" # 默认值
|
|
208
|
+
if isinstance(generator_conf, dict):
|
|
209
|
+
engine_type = generator_conf.get("engine_type", engine_type)
|
|
210
|
+
elif "engine_type" in self.config:
|
|
211
|
+
engine_type = self.config["engine_type"]
|
|
212
|
+
|
|
213
|
+
self.engine_type = engine_type
|
|
214
|
+
self.profile = _build_profile(profile_conf)
|
|
215
|
+
self.generator = _build_generator(generator_conf, engine_type=engine_type)
|
|
216
|
+
self.planner = _build_planner(planner_conf, self.generator)
|
|
217
|
+
self.tools = _build_tools(tools_conf)
|
|
218
|
+
|
|
219
|
+
summarizer_conf = runtime_conf.get("summarizer")
|
|
220
|
+
if summarizer_conf == "reuse_generator":
|
|
221
|
+
self.summarizer = self.generator
|
|
222
|
+
elif summarizer_conf:
|
|
223
|
+
self.summarizer = _build_generator(summarizer_conf)
|
|
224
|
+
else:
|
|
225
|
+
self.summarizer = None
|
|
226
|
+
|
|
227
|
+
self.max_steps = runtime_conf.get("max_steps", 6)
|
|
228
|
+
self.runtime = AgentRuntime(
|
|
229
|
+
profile=self.profile,
|
|
230
|
+
planner=self.planner,
|
|
231
|
+
tools=self.tools,
|
|
232
|
+
summarizer=self.summarizer,
|
|
233
|
+
max_steps=self.max_steps,
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
def execute(self, data: Any) -> Any:
|
|
237
|
+
if isinstance(data, dict):
|
|
238
|
+
return self.runtime.execute(data)
|
|
239
|
+
if isinstance(data, str):
|
|
240
|
+
return self.runtime.execute({"query": data})
|
|
241
|
+
raise TypeError("AgentRuntimeOperator expects str or dict payloads")
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Timing Operator
|
|
3
|
+
|
|
4
|
+
Middleware operator for timing decisions using runtime components.
|
|
5
|
+
|
|
6
|
+
Supports engine_type switching:
|
|
7
|
+
- sagellm (default): SageLLMGenerator with configurable backend
|
|
8
|
+
- backend_type="auto": Automatically select best available backend
|
|
9
|
+
- backend_type="mock": Mock backend for testing without GPU
|
|
10
|
+
- backend_type="cuda": NVIDIA CUDA backend
|
|
11
|
+
- backend_type="ascend": Huawei Ascend NPU backend
|
|
12
|
+
- openai: OpenAIGenerator for OpenAI-compatible APIs
|
|
13
|
+
- hf: HFGenerator for HuggingFace models
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from typing import Any, Optional
|
|
17
|
+
|
|
18
|
+
from sage_libs.sage_agentic.agents.runtime import BenchmarkAdapter, Orchestrator, RuntimeConfig
|
|
19
|
+
from sage_libs.sage_agentic.agents.runtime.config import TimingConfig
|
|
20
|
+
|
|
21
|
+
from sage.common.core.functions import MapFunction
|
|
22
|
+
|
|
23
|
+
from .runtime import _build_generator
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class TimingOperator(MapFunction):
|
|
27
|
+
"""
|
|
28
|
+
Operator for timing decisions.
|
|
29
|
+
|
|
30
|
+
Wraps runtime timing decider in a middleware operator interface.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
timing_decider: Timing decider instance (optional)
|
|
34
|
+
config: Configuration dictionary with optional keys:
|
|
35
|
+
- timing: Timing-specific config
|
|
36
|
+
- generator: Generator config with engine_type/backend_type
|
|
37
|
+
- engine_type: Shorthand for generator.engine_type (sagellm/openai/hf)
|
|
38
|
+
- backend_type: Shorthand for generator.backend_type (auto/mock/cuda/ascend)
|
|
39
|
+
|
|
40
|
+
Example:
|
|
41
|
+
```python
|
|
42
|
+
# Using sagellm with mock backend (for testing)
|
|
43
|
+
operator = TimingOperator(config={
|
|
44
|
+
"generator": {
|
|
45
|
+
"engine_type": "sagellm",
|
|
46
|
+
"backend_type": "mock",
|
|
47
|
+
},
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
# Using default sagellm with auto backend
|
|
51
|
+
operator = TimingOperator(config={
|
|
52
|
+
"engine_type": "sagellm",
|
|
53
|
+
"backend_type": "auto",
|
|
54
|
+
})
|
|
55
|
+
```
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
def __init__(
|
|
59
|
+
self,
|
|
60
|
+
timing_decider: Optional[Any] = None,
|
|
61
|
+
config: Optional[dict[str, Any]] = None,
|
|
62
|
+
):
|
|
63
|
+
"""Initialize timing operator.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
timing_decider: Timing decider instance (optional)
|
|
67
|
+
config: Configuration dictionary
|
|
68
|
+
"""
|
|
69
|
+
super().__init__()
|
|
70
|
+
|
|
71
|
+
# Parse configuration
|
|
72
|
+
if config is None:
|
|
73
|
+
config = {}
|
|
74
|
+
|
|
75
|
+
self.config = config
|
|
76
|
+
|
|
77
|
+
# Build generator if config provided
|
|
78
|
+
generator_conf = config.get("generator", {})
|
|
79
|
+
# Allow shorthand engine_type/backend_type at top level
|
|
80
|
+
if "engine_type" in config and "engine_type" not in generator_conf:
|
|
81
|
+
generator_conf["engine_type"] = config["engine_type"]
|
|
82
|
+
if "backend_type" in config and "backend_type" not in generator_conf:
|
|
83
|
+
generator_conf["backend_type"] = config["backend_type"]
|
|
84
|
+
|
|
85
|
+
# Build generator (defaults to sagellm with auto backend)
|
|
86
|
+
if generator_conf or not timing_decider:
|
|
87
|
+
engine_type = generator_conf.get("engine_type", "sagellm")
|
|
88
|
+
# Ensure we have at least minimal config
|
|
89
|
+
if not generator_conf:
|
|
90
|
+
generator_conf = {"engine_type": "sagellm", "backend_type": "auto"}
|
|
91
|
+
self.generator = _build_generator(generator_conf, engine_type=engine_type)
|
|
92
|
+
else:
|
|
93
|
+
self.generator = None
|
|
94
|
+
|
|
95
|
+
timing_config = TimingConfig(**config.get("timing", {}))
|
|
96
|
+
runtime_config = RuntimeConfig(timing=timing_config)
|
|
97
|
+
|
|
98
|
+
# Create orchestrator
|
|
99
|
+
self.orchestrator = Orchestrator(config=runtime_config, timing_decider=timing_decider)
|
|
100
|
+
|
|
101
|
+
# Create adapter for easy use
|
|
102
|
+
self.adapter = BenchmarkAdapter(self.orchestrator)
|
|
103
|
+
|
|
104
|
+
def __call__(self, message: Any) -> Any:
|
|
105
|
+
"""Execute timing decision.
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
message: Message to evaluate
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
Timing decision
|
|
112
|
+
"""
|
|
113
|
+
return self.adapter.run_timing(message)
|
|
114
|
+
|
|
115
|
+
def execute(self, data: Any) -> Any:
|
|
116
|
+
"""Execute map function interface."""
|
|
117
|
+
return self.__call__(data)
|
|
118
|
+
|
|
119
|
+
def get_metrics(self) -> dict[str, Any]:
|
|
120
|
+
"""Get performance metrics.
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
Dictionary of metrics
|
|
124
|
+
"""
|
|
125
|
+
return self.adapter.get_metrics()
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tool Selection Operator
|
|
3
|
+
|
|
4
|
+
Middleware operator for tool selection using runtime components.
|
|
5
|
+
|
|
6
|
+
Supports engine_type switching:
|
|
7
|
+
- sagellm (default): SageLLMGenerator with configurable backend
|
|
8
|
+
- backend_type="auto": Automatically select best available backend
|
|
9
|
+
- backend_type="mock": Mock backend for testing without GPU
|
|
10
|
+
- backend_type="cuda": NVIDIA CUDA backend
|
|
11
|
+
- backend_type="ascend": Huawei Ascend NPU backend
|
|
12
|
+
- openai: OpenAIGenerator for OpenAI-compatible APIs
|
|
13
|
+
- hf: HFGenerator for HuggingFace models
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from typing import Any, Optional
|
|
17
|
+
|
|
18
|
+
from sage_libs.sage_agentic.agents.runtime import BenchmarkAdapter, Orchestrator, RuntimeConfig
|
|
19
|
+
from sage_libs.sage_agentic.agents.runtime.config import SelectorConfig
|
|
20
|
+
|
|
21
|
+
from sage.common.core.functions import MapFunction
|
|
22
|
+
|
|
23
|
+
from .runtime import _build_generator
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class ToolSelectionOperator(MapFunction):
|
|
27
|
+
"""
|
|
28
|
+
Operator for tool selection.
|
|
29
|
+
|
|
30
|
+
Wraps runtime tool selector in a middleware operator interface.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
selector: Tool selector instance (optional)
|
|
34
|
+
config: Configuration dictionary with optional keys:
|
|
35
|
+
- selector: Selector-specific config (e.g., top_k)
|
|
36
|
+
- generator: Generator config with engine_type/backend_type
|
|
37
|
+
- engine_type: Shorthand for generator.engine_type (sagellm/openai/hf)
|
|
38
|
+
- backend_type: Shorthand for generator.backend_type (auto/mock/cuda/ascend)
|
|
39
|
+
|
|
40
|
+
Example:
|
|
41
|
+
```python
|
|
42
|
+
# Using sagellm with mock backend (for testing)
|
|
43
|
+
operator = ToolSelectionOperator(config={
|
|
44
|
+
"generator": {
|
|
45
|
+
"engine_type": "sagellm",
|
|
46
|
+
"backend_type": "mock",
|
|
47
|
+
},
|
|
48
|
+
"selector": {"top_k": 5},
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
# Using default sagellm with auto backend
|
|
52
|
+
operator = ToolSelectionOperator(config={
|
|
53
|
+
"engine_type": "sagellm",
|
|
54
|
+
"backend_type": "auto",
|
|
55
|
+
})
|
|
56
|
+
```
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
def __init__(
|
|
60
|
+
self,
|
|
61
|
+
selector: Optional[Any] = None,
|
|
62
|
+
config: Optional[dict[str, Any]] = None,
|
|
63
|
+
):
|
|
64
|
+
"""Initialize tool selection operator.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
selector: Tool selector instance (optional)
|
|
68
|
+
config: Configuration dictionary
|
|
69
|
+
"""
|
|
70
|
+
super().__init__()
|
|
71
|
+
|
|
72
|
+
# Parse configuration
|
|
73
|
+
if config is None:
|
|
74
|
+
config = {}
|
|
75
|
+
|
|
76
|
+
self.config = config
|
|
77
|
+
|
|
78
|
+
# Build generator if config provided
|
|
79
|
+
generator_conf = config.get("generator", {})
|
|
80
|
+
# Allow shorthand engine_type/backend_type at top level
|
|
81
|
+
if "engine_type" in config and "engine_type" not in generator_conf:
|
|
82
|
+
generator_conf["engine_type"] = config["engine_type"]
|
|
83
|
+
if "backend_type" in config and "backend_type" not in generator_conf:
|
|
84
|
+
generator_conf["backend_type"] = config["backend_type"]
|
|
85
|
+
|
|
86
|
+
# Build generator (defaults to sagellm with auto backend)
|
|
87
|
+
if generator_conf or not selector:
|
|
88
|
+
engine_type = generator_conf.get("engine_type", "sagellm")
|
|
89
|
+
# Ensure we have at least minimal config
|
|
90
|
+
if not generator_conf:
|
|
91
|
+
generator_conf = {"engine_type": "sagellm", "backend_type": "auto"}
|
|
92
|
+
self.generator = _build_generator(generator_conf, engine_type=engine_type)
|
|
93
|
+
else:
|
|
94
|
+
self.generator = None
|
|
95
|
+
|
|
96
|
+
selector_config = SelectorConfig(**config.get("selector", {}))
|
|
97
|
+
runtime_config = RuntimeConfig(selector=selector_config)
|
|
98
|
+
|
|
99
|
+
# Create orchestrator
|
|
100
|
+
self.orchestrator = Orchestrator(config=runtime_config, selector=selector)
|
|
101
|
+
|
|
102
|
+
# Create adapter for easy use
|
|
103
|
+
self.adapter = BenchmarkAdapter(self.orchestrator)
|
|
104
|
+
|
|
105
|
+
def __call__(self, query: Any) -> list[Any]:
|
|
106
|
+
"""Execute tool selection.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
query: Tool selection query
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
List of selected tools
|
|
113
|
+
"""
|
|
114
|
+
top_k = self.config.get("selector", {}).get("top_k", 5)
|
|
115
|
+
return self.adapter.run_tool_selection(query, top_k=top_k)
|
|
116
|
+
|
|
117
|
+
def execute(self, data: Any) -> list[Any]:
|
|
118
|
+
"""Execute map function interface."""
|
|
119
|
+
return self.__call__(data)
|
|
120
|
+
|
|
121
|
+
def get_metrics(self) -> dict[str, Any]:
|
|
122
|
+
"""Get performance metrics.
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
Dictionary of metrics
|
|
126
|
+
"""
|
|
127
|
+
return self.adapter.get_metrics()
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Business context for Agent and RAG workflows."""
|
|
2
|
+
|
|
3
|
+
from sage.middleware.operators.context.critic_evaluation import CriticEvaluation
|
|
4
|
+
from sage.middleware.operators.context.model_context import ModelContext
|
|
5
|
+
from sage.middleware.operators.context.quality_label import QualityLabel
|
|
6
|
+
from sage.middleware.operators.context.search_query_results import SearchQueryResults
|
|
7
|
+
from sage.middleware.operators.context.search_result import SearchResult
|
|
8
|
+
from sage.middleware.operators.context.search_session import SearchSession
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"ModelContext",
|
|
12
|
+
"SearchSession",
|
|
13
|
+
"CriticEvaluation",
|
|
14
|
+
"QualityLabel",
|
|
15
|
+
"SearchResult",
|
|
16
|
+
"SearchQueryResults",
|
|
17
|
+
]
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
|
|
3
|
+
from .quality_label import QualityLabel
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@dataclass
|
|
7
|
+
class CriticEvaluation:
|
|
8
|
+
"""Critic评估结果"""
|
|
9
|
+
|
|
10
|
+
label: QualityLabel
|
|
11
|
+
confidence: float # 0.0-1.0
|
|
12
|
+
reasoning: str
|
|
13
|
+
specific_issues: list[str] = field(default_factory=list)
|
|
14
|
+
suggestions: list[str] = field(default_factory=list)
|
|
15
|
+
should_return_to_chief: bool = False
|
|
16
|
+
ready_for_output: bool = False
|