kweaver-dolphin 0.1.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.
- DolphinLanguageSDK/__init__.py +58 -0
- dolphin/__init__.py +62 -0
- dolphin/cli/__init__.py +20 -0
- dolphin/cli/args/__init__.py +9 -0
- dolphin/cli/args/parser.py +567 -0
- dolphin/cli/builtin_agents/__init__.py +22 -0
- dolphin/cli/commands/__init__.py +4 -0
- dolphin/cli/interrupt/__init__.py +8 -0
- dolphin/cli/interrupt/handler.py +205 -0
- dolphin/cli/interrupt/keyboard.py +82 -0
- dolphin/cli/main.py +49 -0
- dolphin/cli/multimodal/__init__.py +34 -0
- dolphin/cli/multimodal/clipboard.py +327 -0
- dolphin/cli/multimodal/handler.py +249 -0
- dolphin/cli/multimodal/image_processor.py +214 -0
- dolphin/cli/multimodal/input_parser.py +149 -0
- dolphin/cli/runner/__init__.py +8 -0
- dolphin/cli/runner/runner.py +989 -0
- dolphin/cli/ui/__init__.py +10 -0
- dolphin/cli/ui/console.py +2795 -0
- dolphin/cli/ui/input.py +340 -0
- dolphin/cli/ui/layout.py +425 -0
- dolphin/cli/ui/stream_renderer.py +302 -0
- dolphin/cli/utils/__init__.py +8 -0
- dolphin/cli/utils/helpers.py +135 -0
- dolphin/cli/utils/version.py +49 -0
- dolphin/core/__init__.py +107 -0
- dolphin/core/agent/__init__.py +10 -0
- dolphin/core/agent/agent_state.py +69 -0
- dolphin/core/agent/base_agent.py +970 -0
- dolphin/core/code_block/__init__.py +0 -0
- dolphin/core/code_block/agent_init_block.py +0 -0
- dolphin/core/code_block/assign_block.py +98 -0
- dolphin/core/code_block/basic_code_block.py +1865 -0
- dolphin/core/code_block/explore_block.py +1327 -0
- dolphin/core/code_block/explore_block_v2.py +712 -0
- dolphin/core/code_block/explore_strategy.py +672 -0
- dolphin/core/code_block/judge_block.py +220 -0
- dolphin/core/code_block/prompt_block.py +32 -0
- dolphin/core/code_block/skill_call_deduplicator.py +291 -0
- dolphin/core/code_block/tool_block.py +129 -0
- dolphin/core/common/__init__.py +17 -0
- dolphin/core/common/constants.py +176 -0
- dolphin/core/common/enums.py +1173 -0
- dolphin/core/common/exceptions.py +133 -0
- dolphin/core/common/multimodal.py +539 -0
- dolphin/core/common/object_type.py +165 -0
- dolphin/core/common/output_format.py +432 -0
- dolphin/core/common/types.py +36 -0
- dolphin/core/config/__init__.py +16 -0
- dolphin/core/config/global_config.py +1289 -0
- dolphin/core/config/ontology_config.py +133 -0
- dolphin/core/context/__init__.py +12 -0
- dolphin/core/context/context.py +1580 -0
- dolphin/core/context/context_manager.py +161 -0
- dolphin/core/context/var_output.py +82 -0
- dolphin/core/context/variable_pool.py +356 -0
- dolphin/core/context_engineer/__init__.py +41 -0
- dolphin/core/context_engineer/config/__init__.py +5 -0
- dolphin/core/context_engineer/config/settings.py +402 -0
- dolphin/core/context_engineer/core/__init__.py +7 -0
- dolphin/core/context_engineer/core/budget_manager.py +327 -0
- dolphin/core/context_engineer/core/context_assembler.py +583 -0
- dolphin/core/context_engineer/core/context_manager.py +637 -0
- dolphin/core/context_engineer/core/tokenizer_service.py +260 -0
- dolphin/core/context_engineer/example/incremental_example.py +267 -0
- dolphin/core/context_engineer/example/traditional_example.py +334 -0
- dolphin/core/context_engineer/services/__init__.py +5 -0
- dolphin/core/context_engineer/services/compressor.py +399 -0
- dolphin/core/context_engineer/utils/__init__.py +6 -0
- dolphin/core/context_engineer/utils/context_utils.py +441 -0
- dolphin/core/context_engineer/utils/message_formatter.py +270 -0
- dolphin/core/context_engineer/utils/token_utils.py +139 -0
- dolphin/core/coroutine/__init__.py +15 -0
- dolphin/core/coroutine/context_snapshot.py +154 -0
- dolphin/core/coroutine/context_snapshot_profile.py +922 -0
- dolphin/core/coroutine/context_snapshot_store.py +268 -0
- dolphin/core/coroutine/execution_frame.py +145 -0
- dolphin/core/coroutine/execution_state_registry.py +161 -0
- dolphin/core/coroutine/resume_handle.py +101 -0
- dolphin/core/coroutine/step_result.py +101 -0
- dolphin/core/executor/__init__.py +18 -0
- dolphin/core/executor/debug_controller.py +630 -0
- dolphin/core/executor/dolphin_executor.py +1063 -0
- dolphin/core/executor/executor.py +624 -0
- dolphin/core/flags/__init__.py +27 -0
- dolphin/core/flags/definitions.py +49 -0
- dolphin/core/flags/manager.py +113 -0
- dolphin/core/hook/__init__.py +95 -0
- dolphin/core/hook/expression_evaluator.py +499 -0
- dolphin/core/hook/hook_dispatcher.py +380 -0
- dolphin/core/hook/hook_types.py +248 -0
- dolphin/core/hook/isolated_variable_pool.py +284 -0
- dolphin/core/interfaces.py +53 -0
- dolphin/core/llm/__init__.py +0 -0
- dolphin/core/llm/llm.py +495 -0
- dolphin/core/llm/llm_call.py +100 -0
- dolphin/core/llm/llm_client.py +1285 -0
- dolphin/core/llm/message_sanitizer.py +120 -0
- dolphin/core/logging/__init__.py +20 -0
- dolphin/core/logging/logger.py +526 -0
- dolphin/core/message/__init__.py +8 -0
- dolphin/core/message/compressor.py +749 -0
- dolphin/core/parser/__init__.py +8 -0
- dolphin/core/parser/parser.py +405 -0
- dolphin/core/runtime/__init__.py +10 -0
- dolphin/core/runtime/runtime_graph.py +926 -0
- dolphin/core/runtime/runtime_instance.py +446 -0
- dolphin/core/skill/__init__.py +14 -0
- dolphin/core/skill/context_retention.py +157 -0
- dolphin/core/skill/skill_function.py +686 -0
- dolphin/core/skill/skill_matcher.py +282 -0
- dolphin/core/skill/skillkit.py +700 -0
- dolphin/core/skill/skillset.py +72 -0
- dolphin/core/trajectory/__init__.py +10 -0
- dolphin/core/trajectory/recorder.py +189 -0
- dolphin/core/trajectory/trajectory.py +522 -0
- dolphin/core/utils/__init__.py +9 -0
- dolphin/core/utils/cache_kv.py +212 -0
- dolphin/core/utils/tools.py +340 -0
- dolphin/lib/__init__.py +93 -0
- dolphin/lib/debug/__init__.py +8 -0
- dolphin/lib/debug/visualizer.py +409 -0
- dolphin/lib/memory/__init__.py +28 -0
- dolphin/lib/memory/async_processor.py +220 -0
- dolphin/lib/memory/llm_calls.py +195 -0
- dolphin/lib/memory/manager.py +78 -0
- dolphin/lib/memory/sandbox.py +46 -0
- dolphin/lib/memory/storage.py +245 -0
- dolphin/lib/memory/utils.py +51 -0
- dolphin/lib/ontology/__init__.py +12 -0
- dolphin/lib/ontology/basic/__init__.py +0 -0
- dolphin/lib/ontology/basic/base.py +102 -0
- dolphin/lib/ontology/basic/concept.py +130 -0
- dolphin/lib/ontology/basic/object.py +11 -0
- dolphin/lib/ontology/basic/relation.py +63 -0
- dolphin/lib/ontology/datasource/__init__.py +27 -0
- dolphin/lib/ontology/datasource/datasource.py +66 -0
- dolphin/lib/ontology/datasource/oracle_datasource.py +338 -0
- dolphin/lib/ontology/datasource/sql.py +845 -0
- dolphin/lib/ontology/mapping.py +177 -0
- dolphin/lib/ontology/ontology.py +733 -0
- dolphin/lib/ontology/ontology_context.py +16 -0
- dolphin/lib/ontology/ontology_manager.py +107 -0
- dolphin/lib/skill_results/__init__.py +31 -0
- dolphin/lib/skill_results/cache_backend.py +559 -0
- dolphin/lib/skill_results/result_processor.py +181 -0
- dolphin/lib/skill_results/result_reference.py +179 -0
- dolphin/lib/skill_results/skillkit_hook.py +324 -0
- dolphin/lib/skill_results/strategies.py +328 -0
- dolphin/lib/skill_results/strategy_registry.py +150 -0
- dolphin/lib/skillkits/__init__.py +44 -0
- dolphin/lib/skillkits/agent_skillkit.py +155 -0
- dolphin/lib/skillkits/cognitive_skillkit.py +82 -0
- dolphin/lib/skillkits/env_skillkit.py +250 -0
- dolphin/lib/skillkits/mcp_adapter.py +616 -0
- dolphin/lib/skillkits/mcp_skillkit.py +771 -0
- dolphin/lib/skillkits/memory_skillkit.py +650 -0
- dolphin/lib/skillkits/noop_skillkit.py +31 -0
- dolphin/lib/skillkits/ontology_skillkit.py +89 -0
- dolphin/lib/skillkits/plan_act_skillkit.py +452 -0
- dolphin/lib/skillkits/resource/__init__.py +52 -0
- dolphin/lib/skillkits/resource/models/__init__.py +6 -0
- dolphin/lib/skillkits/resource/models/skill_config.py +109 -0
- dolphin/lib/skillkits/resource/models/skill_meta.py +127 -0
- dolphin/lib/skillkits/resource/resource_skillkit.py +393 -0
- dolphin/lib/skillkits/resource/skill_cache.py +215 -0
- dolphin/lib/skillkits/resource/skill_loader.py +395 -0
- dolphin/lib/skillkits/resource/skill_validator.py +406 -0
- dolphin/lib/skillkits/resource_skillkit.py +11 -0
- dolphin/lib/skillkits/search_skillkit.py +163 -0
- dolphin/lib/skillkits/sql_skillkit.py +274 -0
- dolphin/lib/skillkits/system_skillkit.py +509 -0
- dolphin/lib/skillkits/vm_skillkit.py +65 -0
- dolphin/lib/utils/__init__.py +9 -0
- dolphin/lib/utils/data_process.py +207 -0
- dolphin/lib/utils/handle_progress.py +178 -0
- dolphin/lib/utils/security.py +139 -0
- dolphin/lib/utils/text_retrieval.py +462 -0
- dolphin/lib/vm/__init__.py +11 -0
- dolphin/lib/vm/env_executor.py +895 -0
- dolphin/lib/vm/python_session_manager.py +453 -0
- dolphin/lib/vm/vm.py +610 -0
- dolphin/sdk/__init__.py +60 -0
- dolphin/sdk/agent/__init__.py +12 -0
- dolphin/sdk/agent/agent_factory.py +236 -0
- dolphin/sdk/agent/dolphin_agent.py +1106 -0
- dolphin/sdk/api/__init__.py +4 -0
- dolphin/sdk/runtime/__init__.py +8 -0
- dolphin/sdk/runtime/env.py +363 -0
- dolphin/sdk/skill/__init__.py +10 -0
- dolphin/sdk/skill/global_skills.py +706 -0
- dolphin/sdk/skill/traditional_toolkit.py +260 -0
- kweaver_dolphin-0.1.0.dist-info/METADATA +521 -0
- kweaver_dolphin-0.1.0.dist-info/RECORD +199 -0
- kweaver_dolphin-0.1.0.dist-info/WHEEL +5 -0
- kweaver_dolphin-0.1.0.dist-info/entry_points.txt +27 -0
- kweaver_dolphin-0.1.0.dist-info/licenses/LICENSE.txt +201 -0
- kweaver_dolphin-0.1.0.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
"""Strategy Module
|
|
2
|
+
Provides an abstract interface and concrete implementations for data processing strategies (a unified model based on category)
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
from abc import ABC, abstractmethod
|
|
7
|
+
from typing import Any, Dict, List, TYPE_CHECKING
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from dolphin.lib.skill_results.result_reference import ResultReference
|
|
11
|
+
|
|
12
|
+
from dolphin.core.logging.logger import get_logger
|
|
13
|
+
|
|
14
|
+
logger = get_logger("skill_results")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class BaseStrategy(ABC):
|
|
18
|
+
"""Base class for unified strategies.
|
|
19
|
+
|
|
20
|
+
- Use category to distinguish usage scenarios (e.g., 'llm', 'app', 'export', etc.)
|
|
21
|
+
- Subclasses must set the class attribute category and implement process()
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
# Subclasses should override to specify a concrete category, such as 'llm' or 'app'
|
|
25
|
+
category: str = "generic"
|
|
26
|
+
|
|
27
|
+
def get_category(self) -> str:
|
|
28
|
+
return getattr(self, "category", "generic")
|
|
29
|
+
|
|
30
|
+
def supports(self, category: str) -> bool:
|
|
31
|
+
return self.get_category() == category
|
|
32
|
+
|
|
33
|
+
@abstractmethod
|
|
34
|
+
def process(self, result_reference: "ResultReference", **kwargs) -> Any:
|
|
35
|
+
"""Execute strategy processing and return final data (different categories may return different structures)"""
|
|
36
|
+
raise NotImplementedError
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# ======================== LLM Category Strategy (category='llm') ========================
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class BaseLLMStrategy(BaseStrategy):
|
|
43
|
+
"""Base class for LLM strategies, providing general data transformation methods"""
|
|
44
|
+
|
|
45
|
+
category = "llm"
|
|
46
|
+
|
|
47
|
+
def _convert_to_string(self, data: Any) -> str:
|
|
48
|
+
"""Convert data to string format"""
|
|
49
|
+
if isinstance(data, str):
|
|
50
|
+
return data
|
|
51
|
+
elif isinstance(data, (dict, list)):
|
|
52
|
+
return json.dumps(data, ensure_ascii=False, indent=2)
|
|
53
|
+
else:
|
|
54
|
+
return str(data)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class DefaultLLMStrategy(BaseLLMStrategy):
|
|
58
|
+
|
|
59
|
+
def process(self, result_reference: "ResultReference", **kwargs) -> str:
|
|
60
|
+
try:
|
|
61
|
+
full_result = result_reference.get_full_result()
|
|
62
|
+
if full_result is None:
|
|
63
|
+
return "数据不存在"
|
|
64
|
+
|
|
65
|
+
return self._convert_to_string(full_result)
|
|
66
|
+
except Exception as e:
|
|
67
|
+
logger.error(f"默认LLM策略处理failed: {e}")
|
|
68
|
+
return f"数据处理failed: {str(e)}"
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class SummaryLLMStrategy(BaseLLMStrategy):
|
|
72
|
+
|
|
73
|
+
def process(self, result_reference: "ResultReference", **kwargs) -> str:
|
|
74
|
+
try:
|
|
75
|
+
full_result = result_reference.get_full_result()
|
|
76
|
+
if full_result is None:
|
|
77
|
+
return "数据不存在"
|
|
78
|
+
|
|
79
|
+
max_tokens = kwargs.get("max_tokens", 2000)
|
|
80
|
+
max_chars = max_tokens * 4
|
|
81
|
+
|
|
82
|
+
result_str = self._convert_to_string(full_result)
|
|
83
|
+
if len(result_str) <= max_chars:
|
|
84
|
+
return result_str
|
|
85
|
+
|
|
86
|
+
return self._generate_summary(result_str, max_chars)
|
|
87
|
+
except Exception as e:
|
|
88
|
+
logger.error(f"摘要LLM策略处理failed: {e}")
|
|
89
|
+
return f"摘要生成failed: {str(e)}"
|
|
90
|
+
|
|
91
|
+
def _generate_summary(self, text: str, max_chars: int) -> str:
|
|
92
|
+
if len(text) <= max_chars:
|
|
93
|
+
return text
|
|
94
|
+
start_chars = int(max_chars * 0.6)
|
|
95
|
+
end_chars = int(max_chars * 0.2)
|
|
96
|
+
start_part = text[:start_chars]
|
|
97
|
+
end_part = text[-end_chars:] if end_chars > 0 else ""
|
|
98
|
+
|
|
99
|
+
return f"{start_part}\n\n... (内容已截断) ...\n\n{end_part}"
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
class TruncateLLMStrategy(BaseLLMStrategy):
|
|
103
|
+
|
|
104
|
+
def process(self, result_reference: "ResultReference", **kwargs) -> str:
|
|
105
|
+
try:
|
|
106
|
+
full_result = result_reference.get_full_result()
|
|
107
|
+
if full_result is None:
|
|
108
|
+
return "数据不存在"
|
|
109
|
+
|
|
110
|
+
max_tokens = kwargs.get("max_tokens", 2000)
|
|
111
|
+
max_chars = max_tokens * 4
|
|
112
|
+
|
|
113
|
+
result_str = self._convert_to_string(full_result)
|
|
114
|
+
if len(result_str) <= max_chars:
|
|
115
|
+
return result_str
|
|
116
|
+
|
|
117
|
+
truncated = result_str[:max_chars]
|
|
118
|
+
return (
|
|
119
|
+
f"{truncated}\n\n... (内容已截断,总长度: {len(result_str)} 字符) ..."
|
|
120
|
+
)
|
|
121
|
+
except Exception as e:
|
|
122
|
+
logger.error(f"截取LLM策略处理failed: {e}")
|
|
123
|
+
return f"数据截取failed: {str(e)}"
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
# ====================== APP Category Strategy (category='app') ======================
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
class DefaultAppStrategy(BaseStrategy):
|
|
130
|
+
category = "app"
|
|
131
|
+
|
|
132
|
+
def process(self, result_reference: "ResultReference", **kwargs) -> Dict[str, Any]:
|
|
133
|
+
try:
|
|
134
|
+
full_result = result_reference.get_full_result()
|
|
135
|
+
return full_result
|
|
136
|
+
except Exception as e:
|
|
137
|
+
logger.error(f"默认APP策略处理failed: {e}")
|
|
138
|
+
return {
|
|
139
|
+
"error": f"数据处理failed: {str(e)}",
|
|
140
|
+
"reference_id": result_reference.reference_id,
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
class PaginationAppStrategy(BaseStrategy):
|
|
145
|
+
category = "app"
|
|
146
|
+
|
|
147
|
+
def process(self, result_reference: "ResultReference", **kwargs) -> Dict[str, Any]:
|
|
148
|
+
try:
|
|
149
|
+
full_result = result_reference.get_full_result()
|
|
150
|
+
metadata = result_reference.get_metadata()
|
|
151
|
+
if full_result is None:
|
|
152
|
+
return {
|
|
153
|
+
"error": "数据不存在",
|
|
154
|
+
"reference_id": result_reference.reference_id,
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
page = kwargs.get("page", 1)
|
|
158
|
+
page_size = kwargs.get("page_size", 20)
|
|
159
|
+
|
|
160
|
+
if isinstance(full_result, list):
|
|
161
|
+
return self._paginate_list(
|
|
162
|
+
full_result,
|
|
163
|
+
page,
|
|
164
|
+
page_size,
|
|
165
|
+
metadata,
|
|
166
|
+
result_reference.reference_id,
|
|
167
|
+
)
|
|
168
|
+
elif isinstance(full_result, dict):
|
|
169
|
+
return self._paginate_dict(
|
|
170
|
+
full_result,
|
|
171
|
+
page,
|
|
172
|
+
page_size,
|
|
173
|
+
metadata,
|
|
174
|
+
result_reference.reference_id,
|
|
175
|
+
)
|
|
176
|
+
else:
|
|
177
|
+
return {
|
|
178
|
+
"data": full_result,
|
|
179
|
+
"metadata": metadata,
|
|
180
|
+
"reference_id": result_reference.reference_id,
|
|
181
|
+
"strategy": "pagination",
|
|
182
|
+
"pagination": {
|
|
183
|
+
"page": 1,
|
|
184
|
+
"page_size": 1,
|
|
185
|
+
"total_pages": 1,
|
|
186
|
+
"total_items": 1,
|
|
187
|
+
},
|
|
188
|
+
}
|
|
189
|
+
except Exception as e:
|
|
190
|
+
logger.error(f"分页APP策略处理failed: {e}")
|
|
191
|
+
return {
|
|
192
|
+
"error": f"分页处理failed: {str(e)}",
|
|
193
|
+
"reference_id": result_reference.reference_id,
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
def _paginate_list(
|
|
197
|
+
self,
|
|
198
|
+
data: List[Any],
|
|
199
|
+
page: int,
|
|
200
|
+
page_size: int,
|
|
201
|
+
metadata: Dict[str, Any],
|
|
202
|
+
reference_id: str,
|
|
203
|
+
) -> Dict[str, Any]:
|
|
204
|
+
total_items = len(data)
|
|
205
|
+
total_pages = (total_items + page_size - 1) // page_size
|
|
206
|
+
page = max(1, min(page, total_pages))
|
|
207
|
+
start_idx = (page - 1) * page_size
|
|
208
|
+
end_idx = start_idx + page_size
|
|
209
|
+
page_data = data[start_idx:end_idx]
|
|
210
|
+
return {
|
|
211
|
+
"data": page_data,
|
|
212
|
+
"metadata": metadata,
|
|
213
|
+
"reference_id": reference_id,
|
|
214
|
+
"strategy": "pagination",
|
|
215
|
+
"pagination": {
|
|
216
|
+
"page": page,
|
|
217
|
+
"page_size": page_size,
|
|
218
|
+
"total_pages": total_pages,
|
|
219
|
+
"total_items": total_items,
|
|
220
|
+
"has_next": page < total_pages,
|
|
221
|
+
"has_prev": page > 1,
|
|
222
|
+
},
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
def _paginate_dict(
|
|
226
|
+
self,
|
|
227
|
+
data: Dict[str, Any],
|
|
228
|
+
page: int,
|
|
229
|
+
page_size: int,
|
|
230
|
+
metadata: Dict[str, Any],
|
|
231
|
+
reference_id: str,
|
|
232
|
+
) -> Dict[str, Any]:
|
|
233
|
+
items = list(data.items())
|
|
234
|
+
total_items = len(items)
|
|
235
|
+
total_pages = (total_items + page_size - 1) // page_size
|
|
236
|
+
page = max(1, min(page, total_pages))
|
|
237
|
+
start_idx = (page - 1) * page_size
|
|
238
|
+
end_idx = start_idx + page_size
|
|
239
|
+
page_items = items[start_idx:end_idx]
|
|
240
|
+
page_data = dict(page_items)
|
|
241
|
+
return {
|
|
242
|
+
"data": page_data,
|
|
243
|
+
"metadata": metadata,
|
|
244
|
+
"reference_id": reference_id,
|
|
245
|
+
"strategy": "pagination",
|
|
246
|
+
"pagination": {
|
|
247
|
+
"page": page,
|
|
248
|
+
"page_size": page_size,
|
|
249
|
+
"total_pages": total_pages,
|
|
250
|
+
"total_items": total_items,
|
|
251
|
+
"has_next": page < total_pages,
|
|
252
|
+
"has_prev": page > 1,
|
|
253
|
+
},
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
class PreviewAppStrategy(BaseStrategy):
|
|
258
|
+
category = "app"
|
|
259
|
+
|
|
260
|
+
def process(self, result_reference: "ResultReference", **kwargs) -> Dict[str, Any]:
|
|
261
|
+
try:
|
|
262
|
+
full_result = result_reference.get_full_result()
|
|
263
|
+
metadata = result_reference.get_metadata()
|
|
264
|
+
if full_result is None:
|
|
265
|
+
return {
|
|
266
|
+
"error": "数据不存在",
|
|
267
|
+
"reference_id": result_reference.reference_id,
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
max_size = kwargs.get("max_size", 1000)
|
|
271
|
+
max_items = kwargs.get("max_items", 10)
|
|
272
|
+
|
|
273
|
+
preview_data = self._generate_preview(full_result, max_size, max_items)
|
|
274
|
+
return {
|
|
275
|
+
"preview": preview_data,
|
|
276
|
+
"metadata": metadata,
|
|
277
|
+
"reference_id": result_reference.reference_id,
|
|
278
|
+
"strategy": "preview",
|
|
279
|
+
"type": type(full_result).__name__,
|
|
280
|
+
"truncated": self._is_truncated(full_result, preview_data, max_size),
|
|
281
|
+
}
|
|
282
|
+
except Exception as e:
|
|
283
|
+
logger.error(f"预览APP策略处理failed: {e}")
|
|
284
|
+
return {
|
|
285
|
+
"error": f"预览处理failed: {str(e)}",
|
|
286
|
+
"reference_id": result_reference.reference_id,
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
def _generate_preview(self, data: Any, max_size: int, max_items: int) -> Any:
|
|
290
|
+
"""Generate preview data"""
|
|
291
|
+
if isinstance(data, str):
|
|
292
|
+
if len(data) <= max_size:
|
|
293
|
+
return data
|
|
294
|
+
return data[:max_size] + "..."
|
|
295
|
+
|
|
296
|
+
elif isinstance(data, list):
|
|
297
|
+
if len(data) <= max_items:
|
|
298
|
+
return data
|
|
299
|
+
return data[:max_items] + ["..."]
|
|
300
|
+
|
|
301
|
+
elif isinstance(data, dict):
|
|
302
|
+
items = list(data.items())
|
|
303
|
+
if len(items) <= max_items:
|
|
304
|
+
return data
|
|
305
|
+
preview_dict = dict(items[:max_items])
|
|
306
|
+
preview_dict["..."] = f"还有 {len(items) - max_items} 项"
|
|
307
|
+
return preview_dict
|
|
308
|
+
|
|
309
|
+
else:
|
|
310
|
+
result_str = str(data)
|
|
311
|
+
if len(result_str) <= max_size:
|
|
312
|
+
return data
|
|
313
|
+
return self._truncate_preview(data, max_size)
|
|
314
|
+
|
|
315
|
+
def _is_truncated(self, original: Any, preview: Any, max_size: int) -> bool:
|
|
316
|
+
"""Determine if truncated"""
|
|
317
|
+
if isinstance(original, str):
|
|
318
|
+
return len(original) > max_size
|
|
319
|
+
elif isinstance(original, (list, dict)):
|
|
320
|
+
return len(str(original)) > max_size
|
|
321
|
+
return False
|
|
322
|
+
|
|
323
|
+
def _truncate_preview(self, data: Any, max_size: int) -> str:
|
|
324
|
+
"""Truncate Preview"""
|
|
325
|
+
result_str = str(data)
|
|
326
|
+
if len(result_str) <= max_size:
|
|
327
|
+
return result_str
|
|
328
|
+
return result_str[:max_size] + "..."
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"""Strategy Registrator
|
|
2
|
+
Provides registration, lookup, and management functions for strategies
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Dict, Optional, List, TYPE_CHECKING
|
|
6
|
+
|
|
7
|
+
from .strategies import (
|
|
8
|
+
BaseStrategy,
|
|
9
|
+
DefaultLLMStrategy,
|
|
10
|
+
SummaryLLMStrategy,
|
|
11
|
+
TruncateLLMStrategy,
|
|
12
|
+
DefaultAppStrategy,
|
|
13
|
+
PaginationAppStrategy,
|
|
14
|
+
PreviewAppStrategy,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
from dolphin.core.logging.logger import get_logger
|
|
21
|
+
|
|
22
|
+
logger = get_logger("skill_results")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class StrategyRegistry:
|
|
26
|
+
"""Strategy Registrator
|
|
27
|
+
- Default support category: 'llm', 'app', and other categories can be extended
|
|
28
|
+
- Multiple named strategies can exist under each category
|
|
29
|
+
- Supports registration, lookup, execution, and other operations
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
def __init__(self):
|
|
33
|
+
# Strategies organized by category
|
|
34
|
+
self._strategies: Dict[str, Dict[str, BaseStrategy]] = {}
|
|
35
|
+
self._default_strategies: Dict[str, str] = {}
|
|
36
|
+
|
|
37
|
+
# Register default policy
|
|
38
|
+
self._register_default_strategies()
|
|
39
|
+
|
|
40
|
+
def _register_default_strategies(self):
|
|
41
|
+
"""Register default strategy"""
|
|
42
|
+
# LLM
|
|
43
|
+
self.register("default", DefaultLLMStrategy(), category="llm")
|
|
44
|
+
self.register("summary", SummaryLLMStrategy(), category="llm")
|
|
45
|
+
self.register("truncate", TruncateLLMStrategy(), category="llm")
|
|
46
|
+
|
|
47
|
+
# App
|
|
48
|
+
self.register("default", DefaultAppStrategy(), category="app")
|
|
49
|
+
self.register("pagination", PaginationAppStrategy(), category="app")
|
|
50
|
+
self.register("preview", PreviewAppStrategy(), category="app")
|
|
51
|
+
|
|
52
|
+
# Set default policy
|
|
53
|
+
self._default_strategies = {
|
|
54
|
+
"llm": "default",
|
|
55
|
+
"app": "default",
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
def register(
|
|
59
|
+
self, name: str, strategy: BaseStrategy, category: Optional[str] = None
|
|
60
|
+
) -> None:
|
|
61
|
+
"""Register strategy
|
|
62
|
+
- name: Strategy name
|
|
63
|
+
- strategy: Strategy instance
|
|
64
|
+
- category: Strategy category, if None then use the strategy's own category
|
|
65
|
+
"""
|
|
66
|
+
if category is None:
|
|
67
|
+
category = strategy.get_category()
|
|
68
|
+
|
|
69
|
+
if category not in self._strategies:
|
|
70
|
+
self._strategies[category] = {}
|
|
71
|
+
|
|
72
|
+
self._strategies[category][name] = strategy
|
|
73
|
+
logger.debug(f"注册策略: {category}:{name} -> {strategy.__class__.__name__}")
|
|
74
|
+
|
|
75
|
+
def get_strategy(self, name: str, category: str) -> Optional[BaseStrategy]:
|
|
76
|
+
"""Get strategy
|
|
77
|
+
- name: Strategy name, supports 'llm:summary' / 'app/pagination' format
|
|
78
|
+
- category: Strategy category
|
|
79
|
+
"""
|
|
80
|
+
# Parse the category information in name
|
|
81
|
+
if ":" in name:
|
|
82
|
+
category, name = name.split(":", 1)
|
|
83
|
+
elif "/" in name:
|
|
84
|
+
category, name = name.split("/", 1)
|
|
85
|
+
|
|
86
|
+
# If category is a wildcard, try all supported categories
|
|
87
|
+
if category == "*":
|
|
88
|
+
for k in ("llm", "app"):
|
|
89
|
+
if k in self._strategies and name in self._strategies[k]:
|
|
90
|
+
return self._strategies[k][name]
|
|
91
|
+
return None
|
|
92
|
+
|
|
93
|
+
# If category is a list, try each category
|
|
94
|
+
if isinstance(category, (list, tuple)):
|
|
95
|
+
for k in category:
|
|
96
|
+
if k in self._strategies and name in self._strategies[k]:
|
|
97
|
+
return self._strategies[k][name]
|
|
98
|
+
return None
|
|
99
|
+
|
|
100
|
+
# If category is a wildcard, try all supported categories
|
|
101
|
+
# if category in ("llm", "app"):
|
|
102
|
+
if category in self._strategies and name in self._strategies[category]:
|
|
103
|
+
return self._strategies[category][name]
|
|
104
|
+
|
|
105
|
+
return None
|
|
106
|
+
|
|
107
|
+
def get_default_strategy(self, category: str) -> Optional[BaseStrategy]:
|
|
108
|
+
"""Get default policy"""
|
|
109
|
+
if category not in self._default_strategies:
|
|
110
|
+
return None
|
|
111
|
+
|
|
112
|
+
default_name = self._default_strategies[category]
|
|
113
|
+
return self.get_strategy(default_name, category)
|
|
114
|
+
|
|
115
|
+
def list_strategies(self, category: Optional[str] = None) -> Dict[str, List[str]]:
|
|
116
|
+
"""List all strategies"""
|
|
117
|
+
if category is None:
|
|
118
|
+
return {
|
|
119
|
+
cat: list(strategies.keys())
|
|
120
|
+
for cat, strategies in self._strategies.items()
|
|
121
|
+
}
|
|
122
|
+
elif category in self._strategies:
|
|
123
|
+
return {category: list(self._strategies[category].keys())}
|
|
124
|
+
else:
|
|
125
|
+
return {}
|
|
126
|
+
|
|
127
|
+
def has_strategy(self, name: str, category: str) -> bool:
|
|
128
|
+
"""Check if the specified policy exists"""
|
|
129
|
+
return self.get_strategy(name, category) is not None
|
|
130
|
+
|
|
131
|
+
def remove_strategy(self, name: str, category: str) -> bool:
|
|
132
|
+
"""Remove Strategy"""
|
|
133
|
+
if category in self._strategies and name in self._strategies[category]:
|
|
134
|
+
del self._strategies[category][name]
|
|
135
|
+
logger.debug(f"移除策略: {category}:{name}")
|
|
136
|
+
return True
|
|
137
|
+
return False
|
|
138
|
+
|
|
139
|
+
def clear(self) -> None:
|
|
140
|
+
"""Clear all strategies"""
|
|
141
|
+
self._strategies.clear()
|
|
142
|
+
self._default_strategies.clear()
|
|
143
|
+
logger.debug("清空所有策略")
|
|
144
|
+
|
|
145
|
+
def __len__(self) -> int:
|
|
146
|
+
"""Return total number of strategies"""
|
|
147
|
+
return sum(len(strategies) for strategies in self._strategies.values())
|
|
148
|
+
|
|
149
|
+
def __repr__(self) -> str:
|
|
150
|
+
return f"StrategyRegistry(strategies={len(self)}, categories={list(self._strategies.keys())})"
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""Skillkits 模块 - 内置 Skillkits"""
|
|
3
|
+
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
if TYPE_CHECKING:
|
|
7
|
+
from dolphin.lib.skillkits.search_skillkit import SearchSkillkit
|
|
8
|
+
from dolphin.lib.skillkits.sql_skillkit import SQLSkillkit
|
|
9
|
+
from dolphin.lib.skillkits.memory_skillkit import MemorySkillkit
|
|
10
|
+
from dolphin.lib.skillkits.mcp_skillkit import MCPSkillkit
|
|
11
|
+
from dolphin.lib.skillkits.ontology_skillkit import OntologySkillkit
|
|
12
|
+
from dolphin.lib.skillkits.plan_act_skillkit import PlanActSkillkit
|
|
13
|
+
from dolphin.lib.skillkits.cognitive_skillkit import CognitiveSkillkit
|
|
14
|
+
from dolphin.lib.skillkits.vm_skillkit import VMSkillkit
|
|
15
|
+
from dolphin.lib.skillkits.noop_skillkit import NoopSkillkit
|
|
16
|
+
from dolphin.lib.skillkits.resource_skillkit import ResourceSkillkit
|
|
17
|
+
from dolphin.lib.skillkits.system_skillkit import SystemFunctionsSkillKit
|
|
18
|
+
from dolphin.lib.skillkits.agent_skillkit import AgentSkillKit
|
|
19
|
+
from dolphin.lib.skillkits.env_skillkit import EnvSkillkit
|
|
20
|
+
|
|
21
|
+
_module_lookup = {
|
|
22
|
+
"SearchSkillkit": "dolphin.lib.skillkits.search_skillkit",
|
|
23
|
+
"SQLSkillkit": "dolphin.lib.skillkits.sql_skillkit",
|
|
24
|
+
"MemorySkillkit": "dolphin.lib.skillkits.memory_skillkit",
|
|
25
|
+
"MCPSkillkit": "dolphin.lib.skillkits.mcp_skillkit",
|
|
26
|
+
"OntologySkillkit": "dolphin.lib.skillkits.ontology_skillkit",
|
|
27
|
+
"PlanActSkillkit": "dolphin.lib.skillkits.plan_act_skillkit",
|
|
28
|
+
"CognitiveSkillkit": "dolphin.lib.skillkits.cognitive_skillkit",
|
|
29
|
+
"VMSkillkit": "dolphin.lib.skillkits.vm_skillkit",
|
|
30
|
+
"NoopSkillkit": "dolphin.lib.skillkits.noop_skillkit",
|
|
31
|
+
"ResourceSkillkit": "dolphin.lib.skillkits.resource_skillkit",
|
|
32
|
+
"SystemFunctionsSkillKit": "dolphin.lib.skillkits.system_skillkit",
|
|
33
|
+
"AgentSkillKit": "dolphin.lib.skillkits.agent_skillkit",
|
|
34
|
+
"EnvSkillkit": "dolphin.lib.skillkits.env_skillkit",
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
def __getattr__(name):
|
|
38
|
+
if name in _module_lookup:
|
|
39
|
+
import importlib
|
|
40
|
+
module = importlib.import_module(_module_lookup[name])
|
|
41
|
+
return getattr(module, name)
|
|
42
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
43
|
+
|
|
44
|
+
__all__ = list(_module_lookup.keys())
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
from typing import List, Any
|
|
2
|
+
|
|
3
|
+
from dolphin.core.skill.skillkit import Skillkit
|
|
4
|
+
from dolphin.core.skill.skill_function import SkillFunction
|
|
5
|
+
from dolphin.core.agent.base_agent import BaseAgent
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class AgentSkillKit(Skillkit):
|
|
9
|
+
"""
|
|
10
|
+
AgentSkillKit acts as a bridge between Agent and Skill system
|
|
11
|
+
Converts a single Agent into a callable skill
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
def __init__(self, agent: BaseAgent, agentName: str = None):
|
|
15
|
+
"""
|
|
16
|
+
Initialize AgentSkillKit with an agent
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
agent (BaseAgent): BaseAgent instance to wrap as a skill
|
|
20
|
+
agentName (str, optional): Name for the agent skill. If None, uses agent.get_name()
|
|
21
|
+
"""
|
|
22
|
+
super().__init__()
|
|
23
|
+
self.agent = agent
|
|
24
|
+
self.agentName = agentName or agent.get_name()
|
|
25
|
+
|
|
26
|
+
# Create the agent execution functions
|
|
27
|
+
self._createAgentSkills()
|
|
28
|
+
|
|
29
|
+
def set_context(self, context):
|
|
30
|
+
self.agent.set_context(context)
|
|
31
|
+
|
|
32
|
+
def _createAgentSkills(self):
|
|
33
|
+
"""
|
|
34
|
+
Create OpenAI functions for agent execution
|
|
35
|
+
"""
|
|
36
|
+
# Get agent description for function documentation
|
|
37
|
+
agentDesc = self.agent.get_description()
|
|
38
|
+
|
|
39
|
+
# Create async execution function
|
|
40
|
+
async def arunAgent(query_str: str = None, **kwargs) -> Any:
|
|
41
|
+
"""
|
|
42
|
+
Execute the agent asynchronously
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
query_str (str, optional): Query or task description to pass to the agent
|
|
46
|
+
**kwargs: Additional arguments to pass to the agent
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
Agent execution result
|
|
50
|
+
"""
|
|
51
|
+
lastResult = None
|
|
52
|
+
# Use query_str if provided, otherwise use query, with query_str taking priority
|
|
53
|
+
queryParam = query_str
|
|
54
|
+
|
|
55
|
+
# Prepare arguments for agent.arun()
|
|
56
|
+
agentArgs = kwargs.copy()
|
|
57
|
+
if queryParam is not None:
|
|
58
|
+
agentArgs["query"] = queryParam
|
|
59
|
+
|
|
60
|
+
await self.agent.initialize()
|
|
61
|
+
async for result in self.agent.arun(**agentArgs):
|
|
62
|
+
lastResult = result
|
|
63
|
+
|
|
64
|
+
#return variables and last stage answer
|
|
65
|
+
result = {}
|
|
66
|
+
if isinstance(lastResult, dict):
|
|
67
|
+
for k, v in lastResult.items():
|
|
68
|
+
if not k.startswith("_"):
|
|
69
|
+
result[k] = v
|
|
70
|
+
elif k == "_progress":
|
|
71
|
+
if len(v) > 1:
|
|
72
|
+
result.update(v[-1])
|
|
73
|
+
return result
|
|
74
|
+
|
|
75
|
+
# Update function names and docstrings dynamically
|
|
76
|
+
arunAgent.__name__ = f"{self.agentName}"
|
|
77
|
+
|
|
78
|
+
# Use agent description if available, otherwise use default description
|
|
79
|
+
if agentDesc:
|
|
80
|
+
arunAgent.__doc__ = f"""
|
|
81
|
+
{agentDesc}
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
query_str (str, optional): Query or task description to pass to the agent
|
|
85
|
+
query (str, optional): Alternative parameter name for backward compatibility
|
|
86
|
+
**kwargs: Additional arguments to pass to the agent
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
Agent execution result
|
|
90
|
+
"""
|
|
91
|
+
else:
|
|
92
|
+
arunAgent.__doc__ = f"""
|
|
93
|
+
Execute agent '{self.agentName}' asynchronously
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
query_str (str, optional): Query or task description to pass to the agent
|
|
97
|
+
query (str, optional): Alternative parameter name for backward compatibility
|
|
98
|
+
**kwargs: Additional arguments to pass to the agent
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
Agent execution result
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
# Store function references
|
|
105
|
+
self.arunAgentFunc = arunAgent
|
|
106
|
+
|
|
107
|
+
def getName(self) -> str:
|
|
108
|
+
"""
|
|
109
|
+
Get the skillkit name
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
Skillkit name
|
|
113
|
+
"""
|
|
114
|
+
return f"agent_skillkit_{self.agentName}"
|
|
115
|
+
|
|
116
|
+
def _createSkills(self) -> List[SkillFunction]:
|
|
117
|
+
"""
|
|
118
|
+
Create the skills (OpenAI functions) for this agent
|
|
119
|
+
|
|
120
|
+
Returns:
|
|
121
|
+
List of SkillFunction objects
|
|
122
|
+
"""
|
|
123
|
+
skills = []
|
|
124
|
+
|
|
125
|
+
# Add async execution function (with arun_ prefix for backward compatibility)
|
|
126
|
+
skills.append(SkillFunction(self.arunAgentFunc))
|
|
127
|
+
|
|
128
|
+
return skills
|
|
129
|
+
|
|
130
|
+
def getAgent(self) -> BaseAgent:
|
|
131
|
+
"""
|
|
132
|
+
Get the wrapped agent
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
BaseAgent instance
|
|
136
|
+
"""
|
|
137
|
+
return self.agent
|
|
138
|
+
|
|
139
|
+
def getAgentName(self) -> str:
|
|
140
|
+
"""
|
|
141
|
+
Get the agent name
|
|
142
|
+
|
|
143
|
+
Returns:
|
|
144
|
+
Agent name string
|
|
145
|
+
"""
|
|
146
|
+
return self.agentName
|
|
147
|
+
|
|
148
|
+
def __str__(self) -> str:
|
|
149
|
+
"""
|
|
150
|
+
String representation of the AgentSkillKit
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
Description string
|
|
154
|
+
"""
|
|
155
|
+
return f"AgentSkillKit(agent={self.agentName})"
|