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,165 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
from typing import Dict, Any, List, Optional
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ObjectType:
|
|
7
|
+
def __init__(
|
|
8
|
+
self,
|
|
9
|
+
title: str,
|
|
10
|
+
description: str,
|
|
11
|
+
properties: Dict[str, Dict[str, Any]],
|
|
12
|
+
required: List[str],
|
|
13
|
+
):
|
|
14
|
+
self.title: str = title
|
|
15
|
+
self.description: str = description
|
|
16
|
+
self.properties: Dict[str, Dict[str, Any]] = properties
|
|
17
|
+
self.required: List[str] = required
|
|
18
|
+
|
|
19
|
+
@classmethod
|
|
20
|
+
def load(cls, jsonData: Dict[str, Any]) -> "ObjectType":
|
|
21
|
+
"""
|
|
22
|
+
Load and validate ObjectType from JSON data.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
jsonData: Dictionary representing the ObjectType.
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
An ObjectType instance.
|
|
29
|
+
|
|
30
|
+
Raises:
|
|
31
|
+
ValueError: If the JSON data format is invalid.
|
|
32
|
+
"""
|
|
33
|
+
requiredFields = ["title", "description", "type", "properties"]
|
|
34
|
+
for field in requiredFields:
|
|
35
|
+
if field not in jsonData:
|
|
36
|
+
raise ValueError(f"Missing required field: {field}")
|
|
37
|
+
|
|
38
|
+
if jsonData.get("type") != "object":
|
|
39
|
+
raise ValueError(f"Type must be 'object', but got '{jsonData.get('type')}'")
|
|
40
|
+
|
|
41
|
+
title = jsonData["title"]
|
|
42
|
+
description = jsonData["description"]
|
|
43
|
+
properties = jsonData["properties"]
|
|
44
|
+
required = jsonData.get(
|
|
45
|
+
"required", []
|
|
46
|
+
) # required is optional, but should be a list if present
|
|
47
|
+
|
|
48
|
+
if not isinstance(title, str) or not title:
|
|
49
|
+
raise ValueError("Field 'title' must be a non-empty string")
|
|
50
|
+
if not isinstance(description, str):
|
|
51
|
+
raise ValueError("Field 'description' must be a string")
|
|
52
|
+
if not isinstance(properties, dict):
|
|
53
|
+
raise ValueError("Field 'properties' must be a dictionary")
|
|
54
|
+
if not isinstance(required, list):
|
|
55
|
+
raise ValueError("Field 'required' must be a list")
|
|
56
|
+
|
|
57
|
+
# Validate properties structure and required list
|
|
58
|
+
for propName, propData in properties.items():
|
|
59
|
+
if not isinstance(propData, dict):
|
|
60
|
+
raise ValueError(f"Value of property '{propName}' must be a dictionary")
|
|
61
|
+
if "type" not in propData or not isinstance(propData["type"], str):
|
|
62
|
+
raise ValueError(
|
|
63
|
+
f"Property '{propName}' is missing or has an invalid 'type' field"
|
|
64
|
+
)
|
|
65
|
+
# Further validation based on type could be added here
|
|
66
|
+
if "description" not in propData or not isinstance(
|
|
67
|
+
propData["description"], str
|
|
68
|
+
):
|
|
69
|
+
raise ValueError(
|
|
70
|
+
f"Property '{propName}' is missing or has an invalid 'description' field"
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
for reqProp in required:
|
|
74
|
+
if reqProp not in properties:
|
|
75
|
+
raise ValueError(
|
|
76
|
+
f"Required property '{reqProp}' is not defined in properties"
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
return cls(
|
|
80
|
+
title=title,
|
|
81
|
+
description=description,
|
|
82
|
+
properties=properties,
|
|
83
|
+
required=required,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class ObjectTypeFactory:
|
|
88
|
+
def __init__(self):
|
|
89
|
+
self.objectTypes: Dict[str, ObjectType] = {}
|
|
90
|
+
|
|
91
|
+
def load_from_json(self, json_data: Dict[str, Any]):
|
|
92
|
+
try:
|
|
93
|
+
objectTypeInstance = ObjectType.load(json_data)
|
|
94
|
+
self.objectTypes[objectTypeInstance.title] = objectTypeInstance
|
|
95
|
+
except Exception as e:
|
|
96
|
+
raise Exception(
|
|
97
|
+
f"An unexpected error occurred while loading ObjectType from {json_data}: {e}"
|
|
98
|
+
) from e
|
|
99
|
+
|
|
100
|
+
def load(self, filepath: str):
|
|
101
|
+
"""
|
|
102
|
+
Load an ObjectType from the specified .type file.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
filepath: The path to the .type file.
|
|
106
|
+
|
|
107
|
+
Raises:
|
|
108
|
+
FileNotFoundError: If the file does not exist or is not a file.
|
|
109
|
+
ValueError: If the file content is not valid JSON or the ObjectType definition is invalid.
|
|
110
|
+
json.JSONDecodeError: If the file content is not valid JSON.
|
|
111
|
+
Exception: For other unexpected errors during file processing.
|
|
112
|
+
"""
|
|
113
|
+
if not os.path.isfile(filepath):
|
|
114
|
+
raise FileNotFoundError(f"File not found or is not a file: {filepath}")
|
|
115
|
+
|
|
116
|
+
with open(filepath, "r", encoding="utf-8") as f:
|
|
117
|
+
jsonData = json.load(f)
|
|
118
|
+
|
|
119
|
+
self.load_from_json(jsonData)
|
|
120
|
+
|
|
121
|
+
def getTypes(self, titles: Optional[List[str]] = None) -> List[ObjectType]:
|
|
122
|
+
"""
|
|
123
|
+
Get all loaded ObjectType instances.
|
|
124
|
+
|
|
125
|
+
Returns:
|
|
126
|
+
A list of all loaded ObjectType instances.
|
|
127
|
+
"""
|
|
128
|
+
if titles is None:
|
|
129
|
+
return list(self.objectTypes.values())
|
|
130
|
+
else:
|
|
131
|
+
for title in titles:
|
|
132
|
+
if title not in self.objectTypes:
|
|
133
|
+
raise ValueError(f"ObjectType title '{title}' not found")
|
|
134
|
+
return [self.objectTypes[title] for title in titles]
|
|
135
|
+
|
|
136
|
+
@staticmethod
|
|
137
|
+
def getOpenaiJsonSchema(objectTypes: List[ObjectType]) -> Dict[str, Any]:
|
|
138
|
+
"""
|
|
139
|
+
Convert a list of ObjectType instances to OpenAI JSON Schema format.
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
objectTypes: A list of ObjectType instances.
|
|
143
|
+
|
|
144
|
+
Returns:
|
|
145
|
+
A string representing the OpenAI JSON Schema for tools/functions.
|
|
146
|
+
"""
|
|
147
|
+
schemas = []
|
|
148
|
+
for objectType in objectTypes:
|
|
149
|
+
schema = {
|
|
150
|
+
"type": "function",
|
|
151
|
+
"function": {
|
|
152
|
+
"name": objectType.title,
|
|
153
|
+
"description": objectType.description,
|
|
154
|
+
"parameters": {
|
|
155
|
+
"type": "object",
|
|
156
|
+
"properties": objectType.properties,
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
}
|
|
160
|
+
# Only include 'required' key if the list is not empty
|
|
161
|
+
if objectType.required:
|
|
162
|
+
schema["function"]["parameters"]["required"] = objectType.required
|
|
163
|
+
|
|
164
|
+
schemas.append(schema)
|
|
165
|
+
return schemas
|
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import Dict, Any, List
|
|
3
|
+
from enum import Enum
|
|
4
|
+
|
|
5
|
+
from dolphin.core.common.enums import MessageRole
|
|
6
|
+
|
|
7
|
+
# Import existing JSON utilities
|
|
8
|
+
from dolphin.core.utils.tools import (
|
|
9
|
+
safe_json_loads,
|
|
10
|
+
)
|
|
11
|
+
from dolphin.core.logging.logger import get_logger
|
|
12
|
+
|
|
13
|
+
logger = get_logger("type")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class OutputFormatType(Enum):
|
|
17
|
+
"""Enum for output format types"""
|
|
18
|
+
|
|
19
|
+
JSON = "json"
|
|
20
|
+
JSONL = "jsonl"
|
|
21
|
+
OBJECT = "object"
|
|
22
|
+
LIST_STR = "list_str"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class OutputFormat(ABC):
|
|
26
|
+
"""Abstract base class for output format
|
|
27
|
+
|
|
28
|
+
Defines the standard interface for output format handling:
|
|
29
|
+
1. Add format constraint prompts
|
|
30
|
+
2. Parse response results
|
|
31
|
+
3. Get format description information
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
def __init__(self, formatType: OutputFormatType):
|
|
35
|
+
"""Initialize output format
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
formatType: Output format type
|
|
39
|
+
"""
|
|
40
|
+
self.formatType = formatType
|
|
41
|
+
|
|
42
|
+
@abstractmethod
|
|
43
|
+
def addFormatConstraintToMessages(self, messages) -> None:
|
|
44
|
+
"""Add format constraint prompts to Messages
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
messages: Messages object, used to add format constraint prompts
|
|
48
|
+
"""
|
|
49
|
+
pass
|
|
50
|
+
|
|
51
|
+
@abstractmethod
|
|
52
|
+
def parseResponse(self, responseStr: str) -> Any:
|
|
53
|
+
"""Parse the response string into the corresponding data structure
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
responseStr: The string of the LLM response
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
The parsed data structure
|
|
60
|
+
"""
|
|
61
|
+
pass
|
|
62
|
+
|
|
63
|
+
@abstractmethod
|
|
64
|
+
def getFormatDescription(self) -> str:
|
|
65
|
+
"""Get the format description for explaining output format requirements to users.
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
Format description string
|
|
69
|
+
"""
|
|
70
|
+
pass
|
|
71
|
+
|
|
72
|
+
def getFormatType(self) -> OutputFormatType:
|
|
73
|
+
"""Get output format type"""
|
|
74
|
+
return self.formatType
|
|
75
|
+
|
|
76
|
+
def toDict(self) -> Dict[str, Any]:
|
|
77
|
+
"""Convert the output format to dictionary format
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
Dictionary representation of format information
|
|
81
|
+
"""
|
|
82
|
+
return {"format_type": self.formatType.value}
|
|
83
|
+
|
|
84
|
+
def __str__(self) -> str:
|
|
85
|
+
"""String Representation"""
|
|
86
|
+
return self.formatType.value
|
|
87
|
+
|
|
88
|
+
def __repr__(self) -> str:
|
|
89
|
+
"""Debug string representation"""
|
|
90
|
+
return f"{self.__class__.__name__}(format={self.formatType.value})"
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class JsonOutputFormat(OutputFormat):
|
|
94
|
+
"""JSON format output processor"""
|
|
95
|
+
|
|
96
|
+
def __init__(self):
|
|
97
|
+
super().__init__(OutputFormatType.JSON)
|
|
98
|
+
|
|
99
|
+
def addFormatConstraintToMessages(self, messages) -> None:
|
|
100
|
+
"""Add JSON format constraints to Messages"""
|
|
101
|
+
constraint_message = (
|
|
102
|
+
"请以标准 JSON 格式输出结果。确保输出是有效的 JSON 对象,"
|
|
103
|
+
"不要包含任何额外的文本说明或代码块标记。"
|
|
104
|
+
)
|
|
105
|
+
messages.append_message(MessageRole.USER, constraint_message)
|
|
106
|
+
|
|
107
|
+
def parseResponse(self, responseStr: str) -> Dict[str, Any]:
|
|
108
|
+
"""Parse JSON response into a dictionary
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
responseStr: Response string
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
Parsed dictionary object
|
|
115
|
+
|
|
116
|
+
Raises:
|
|
117
|
+
ValueError: If JSON parsing fails
|
|
118
|
+
"""
|
|
119
|
+
from dolphin.core.utils.tools import extract_json
|
|
120
|
+
|
|
121
|
+
result = extract_json(responseStr)
|
|
122
|
+
if result is None:
|
|
123
|
+
logger.error("Failed to parse JSON response")
|
|
124
|
+
logger.error(f"Response content: {responseStr}")
|
|
125
|
+
raise ValueError("Invalid JSON format in response")
|
|
126
|
+
|
|
127
|
+
return result
|
|
128
|
+
|
|
129
|
+
def getFormatDescription(self) -> str:
|
|
130
|
+
"""Get JSON format description"""
|
|
131
|
+
return "输出格式:标准 JSON 对象"
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class JsonlOutputFormat(OutputFormat):
|
|
135
|
+
"""JSONL format output processor"""
|
|
136
|
+
|
|
137
|
+
def __init__(self):
|
|
138
|
+
super().__init__(OutputFormatType.JSONL)
|
|
139
|
+
|
|
140
|
+
def addFormatConstraintToMessages(self, messages) -> None:
|
|
141
|
+
"""Add JSONL format constraints to Messages"""
|
|
142
|
+
constraint_message = "请以 JSON Lines (JSONL) 格式输出结果,不要包含任何额外的文本说明或代码块标记。"
|
|
143
|
+
messages.append_message(MessageRole.USER, constraint_message)
|
|
144
|
+
|
|
145
|
+
def parseResponse(self, responseStr: str) -> List[Dict[str, Any]]:
|
|
146
|
+
"""Parse JSONL response into a list of dictionaries
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
responseStr: Response string
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
List of parsed dictionaries
|
|
153
|
+
|
|
154
|
+
Raises:
|
|
155
|
+
ValueError: If JSONL parsing fails
|
|
156
|
+
"""
|
|
157
|
+
from dolphin.core.utils.tools import extract_jsonl
|
|
158
|
+
|
|
159
|
+
results = extract_jsonl(responseStr)
|
|
160
|
+
if results is None:
|
|
161
|
+
logger.error("Failed to parse JSONL response")
|
|
162
|
+
logger.error(f"Response content: {responseStr}")
|
|
163
|
+
raise ValueError("Invalid JSONL format in response")
|
|
164
|
+
return results
|
|
165
|
+
|
|
166
|
+
def getFormatDescription(self) -> str:
|
|
167
|
+
"""Get JSONL format description"""
|
|
168
|
+
return "输出格式:JSON Lines,每行一个 JSON 对象"
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
class ListStrOutputFormat(OutputFormat):
|
|
172
|
+
"""List string format output processor, output format is List[str]"""
|
|
173
|
+
|
|
174
|
+
def __init__(self):
|
|
175
|
+
super().__init__(OutputFormatType.LIST_STR)
|
|
176
|
+
|
|
177
|
+
def addFormatConstraintToMessages(self, messages) -> None:
|
|
178
|
+
"""Add list string format constraints to Messages"""
|
|
179
|
+
constraint_message = (
|
|
180
|
+
"请以字符串列表格式输出结果。输出一个包含多个字符串元素的列表,"
|
|
181
|
+
'格式为JSON数组,每个元素都是字符串类型,例如:["item1", "item2", "item3"]。'
|
|
182
|
+
"不要包含任何额外的文本说明或代码块标记。"
|
|
183
|
+
)
|
|
184
|
+
messages.append_message(MessageRole.USER, constraint_message)
|
|
185
|
+
|
|
186
|
+
def parseResponse(self, responseStr: str) -> List[str]:
|
|
187
|
+
"""Parse a list string response into a string list
|
|
188
|
+
|
|
189
|
+
Args:
|
|
190
|
+
responseStr: Response string
|
|
191
|
+
|
|
192
|
+
Returns:
|
|
193
|
+
Parsed string list
|
|
194
|
+
|
|
195
|
+
Raises:
|
|
196
|
+
ValueError: If list parsing fails
|
|
197
|
+
"""
|
|
198
|
+
# Try to parse directly as JSON
|
|
199
|
+
try:
|
|
200
|
+
result = safe_json_loads(responseStr.strip())
|
|
201
|
+
if isinstance(result, list) and all(
|
|
202
|
+
isinstance(item, str) for item in result
|
|
203
|
+
):
|
|
204
|
+
return result
|
|
205
|
+
else:
|
|
206
|
+
# If not a list of strings, attempt to convert to a list of strings
|
|
207
|
+
if isinstance(result, list):
|
|
208
|
+
return [str(item) for item in result]
|
|
209
|
+
else:
|
|
210
|
+
raise ValueError("Response is not a list")
|
|
211
|
+
except ValueError:
|
|
212
|
+
# Direct parsing failed, try extracting JSON content
|
|
213
|
+
pass
|
|
214
|
+
|
|
215
|
+
# Try to extract a JSON array from the response
|
|
216
|
+
try:
|
|
217
|
+
from dolphin.core.utils.tools import extract_json
|
|
218
|
+
|
|
219
|
+
result = extract_json(responseStr)
|
|
220
|
+
if isinstance(result, list):
|
|
221
|
+
# Ensure all elements are strings
|
|
222
|
+
return [str(item) for item in result]
|
|
223
|
+
else:
|
|
224
|
+
raise ValueError("Extracted content is not a list")
|
|
225
|
+
except ValueError:
|
|
226
|
+
pass
|
|
227
|
+
|
|
228
|
+
# If JSON parsing fails, try simple line splitting
|
|
229
|
+
logger.warning("Failed to parse as JSON list, attempting line-based parsing")
|
|
230
|
+
lines = [
|
|
231
|
+
line.strip() for line in responseStr.strip().split("\n") if line.strip()
|
|
232
|
+
]
|
|
233
|
+
if lines:
|
|
234
|
+
return lines
|
|
235
|
+
|
|
236
|
+
# Fallback: Return the original response as a list of a single string
|
|
237
|
+
logger.warning(
|
|
238
|
+
"All parsing methods failed, returning response as single string list"
|
|
239
|
+
)
|
|
240
|
+
return [responseStr.strip()]
|
|
241
|
+
|
|
242
|
+
def getFormatDescription(self) -> str:
|
|
243
|
+
"""Get list string format description"""
|
|
244
|
+
return "输出格式:字符串列表 List[str]"
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
class ObjectTypeOutputFormat(OutputFormat):
|
|
248
|
+
"""Object type format output processor"""
|
|
249
|
+
|
|
250
|
+
def __init__(self, objectTypeName: str, objectTypeDefinition: Dict[str, Any]):
|
|
251
|
+
"""Initialize object type output format
|
|
252
|
+
|
|
253
|
+
Args:
|
|
254
|
+
objectTypeName: Object type name
|
|
255
|
+
objectTypeDefinition: Object type definition
|
|
256
|
+
"""
|
|
257
|
+
super().__init__(OutputFormatType.OBJECT)
|
|
258
|
+
self.objectTypeName = objectTypeName
|
|
259
|
+
self.objectTypeDefinition = objectTypeDefinition
|
|
260
|
+
|
|
261
|
+
def addFormatConstraintToMessages(self, messages) -> None:
|
|
262
|
+
"""Add object type format constraints to Messages"""
|
|
263
|
+
constraint_message = self._buildConstraintMessage()
|
|
264
|
+
messages.append_message(MessageRole.USER, constraint_message)
|
|
265
|
+
|
|
266
|
+
def _buildConstraintMessage(self) -> str:
|
|
267
|
+
"""Build object type format constraint message
|
|
268
|
+
|
|
269
|
+
For ObjectType format, the specific schema is passed through function call tools,
|
|
270
|
+
here we only need to indicate that tool invocation should be used
|
|
271
|
+
"""
|
|
272
|
+
return f"请使用 {self.objectTypeName} 工具调用来生成结构化输出。"
|
|
273
|
+
|
|
274
|
+
def generateFunctionCallTools(self) -> List[Dict[str, Any]]:
|
|
275
|
+
"""Generate the tools parameter value for function_call
|
|
276
|
+
|
|
277
|
+
Returns:
|
|
278
|
+
List of tool definitions, used for LLM's function_call
|
|
279
|
+
"""
|
|
280
|
+
if not self.objectTypeDefinition:
|
|
281
|
+
raise ValueError(
|
|
282
|
+
f"Object type definition not found for '{self.objectTypeName}'"
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
tool_definition = {
|
|
286
|
+
"type": "function",
|
|
287
|
+
"function": {
|
|
288
|
+
"name": self.objectTypeName,
|
|
289
|
+
"description": self.objectTypeDefinition.get(
|
|
290
|
+
"description", f"{self.objectTypeName} object"
|
|
291
|
+
),
|
|
292
|
+
"parameters": {
|
|
293
|
+
"type": "object",
|
|
294
|
+
"properties": self.objectTypeDefinition.get("properties", {}),
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
# Only add when the required list is not empty
|
|
300
|
+
required = self.objectTypeDefinition.get("required", [])
|
|
301
|
+
if required:
|
|
302
|
+
tool_definition["function"]["parameters"]["required"] = required
|
|
303
|
+
|
|
304
|
+
return [tool_definition]
|
|
305
|
+
|
|
306
|
+
def parseResponse(self, responseStr: str) -> Dict[str, Any]:
|
|
307
|
+
"""Parse object type response
|
|
308
|
+
|
|
309
|
+
For object types, the response is usually the parameter of function_call,
|
|
310
|
+
but it may also be a JSON-formatted object definition.
|
|
311
|
+
|
|
312
|
+
Args:
|
|
313
|
+
responseStr: Response string
|
|
314
|
+
|
|
315
|
+
Returns:
|
|
316
|
+
Parsed object
|
|
317
|
+
"""
|
|
318
|
+
try:
|
|
319
|
+
from dolphin.core.utils.tools import extract_json
|
|
320
|
+
|
|
321
|
+
return extract_json(responseStr)
|
|
322
|
+
except ValueError:
|
|
323
|
+
# Both JSON extraction and parsing have failed, return the original string as the content field.
|
|
324
|
+
pass
|
|
325
|
+
|
|
326
|
+
# If parsing fails, return the original string as the content field
|
|
327
|
+
logger.warning(
|
|
328
|
+
"Failed to parse object type response as JSON, returning as text content"
|
|
329
|
+
)
|
|
330
|
+
return {"content": responseStr}
|
|
331
|
+
|
|
332
|
+
def getFormatDescription(self) -> str:
|
|
333
|
+
"""Get object type format description"""
|
|
334
|
+
return f"输出格式:{self.objectTypeName} 对象类型"
|
|
335
|
+
|
|
336
|
+
def getObjectTypeName(self) -> str:
|
|
337
|
+
"""Get object type name"""
|
|
338
|
+
return self.objectTypeName
|
|
339
|
+
|
|
340
|
+
def getObjectTypeDefinition(self) -> Dict[str, Any]:
|
|
341
|
+
"""Get object type definition"""
|
|
342
|
+
return self.objectTypeDefinition
|
|
343
|
+
|
|
344
|
+
def toDict(self) -> Dict[str, Any]:
|
|
345
|
+
"""Convert the output format to dictionary format"""
|
|
346
|
+
result = super().toDict()
|
|
347
|
+
result.update(
|
|
348
|
+
{
|
|
349
|
+
"object_type_name": self.objectTypeName,
|
|
350
|
+
"object_type_definition": self.objectTypeDefinition,
|
|
351
|
+
}
|
|
352
|
+
)
|
|
353
|
+
return result
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
class OutputFormatFactory:
|
|
357
|
+
"""Format factory class"""
|
|
358
|
+
|
|
359
|
+
@staticmethod
|
|
360
|
+
def parseFromString(outputValue: str, globalTypes=None) -> OutputFormat:
|
|
361
|
+
"""Parse output format from string
|
|
362
|
+
|
|
363
|
+
Args:
|
|
364
|
+
outputValue: Output format string, such as "json", "jsonl", "obj/UserProfile"
|
|
365
|
+
globalTypes: ObjectTypeFactory instance, used to retrieve object type definitions
|
|
366
|
+
|
|
367
|
+
Returns:
|
|
368
|
+
An OutputFormat instance
|
|
369
|
+
|
|
370
|
+
Raises:
|
|
371
|
+
ValueError: When the format is invalid or the object type does not exist
|
|
372
|
+
"""
|
|
373
|
+
if not outputValue or not outputValue.strip():
|
|
374
|
+
raise ValueError("Output format value cannot be empty")
|
|
375
|
+
|
|
376
|
+
outputValue = outputValue.strip().strip('"').strip("'")
|
|
377
|
+
|
|
378
|
+
# Processing JSON format
|
|
379
|
+
if outputValue.lower() == "json":
|
|
380
|
+
return JsonOutputFormat()
|
|
381
|
+
|
|
382
|
+
# Processing JSONL format
|
|
383
|
+
elif outputValue.lower() == "jsonl":
|
|
384
|
+
return JsonlOutputFormat()
|
|
385
|
+
|
|
386
|
+
# Process list string format
|
|
387
|
+
elif outputValue.lower() == "list_str":
|
|
388
|
+
return ListStrOutputFormat()
|
|
389
|
+
|
|
390
|
+
# Object type format: obj/TypeName
|
|
391
|
+
elif outputValue.startswith("obj/"):
|
|
392
|
+
objectTypeName = outputValue[4:] # Remove the "obj/" prefix
|
|
393
|
+
|
|
394
|
+
if not objectTypeName:
|
|
395
|
+
raise ValueError(
|
|
396
|
+
"Object type name cannot be empty in 'obj/TypeName' format"
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
# Get type definitions from global_types
|
|
400
|
+
objectTypeDefinition = None
|
|
401
|
+
if globalTypes:
|
|
402
|
+
try:
|
|
403
|
+
objectTypes = globalTypes.getTypes([objectTypeName])
|
|
404
|
+
if objectTypes:
|
|
405
|
+
objectType = objectTypes[0]
|
|
406
|
+
objectTypeDefinition = {
|
|
407
|
+
"title": objectType.title,
|
|
408
|
+
"description": objectType.description,
|
|
409
|
+
"type": "object",
|
|
410
|
+
"properties": objectType.properties,
|
|
411
|
+
"required": objectType.required,
|
|
412
|
+
}
|
|
413
|
+
except Exception as e:
|
|
414
|
+
logger.warning(
|
|
415
|
+
f"Failed to get object type '{objectTypeName}' from global_types: {e}"
|
|
416
|
+
)
|
|
417
|
+
raise ValueError(
|
|
418
|
+
f"Object type '{objectTypeName}' not found in global_types"
|
|
419
|
+
)
|
|
420
|
+
else:
|
|
421
|
+
logger.warning(
|
|
422
|
+
"global_types not provided, object type definition will be None"
|
|
423
|
+
)
|
|
424
|
+
raise ValueError("global_types is required for object type format")
|
|
425
|
+
|
|
426
|
+
return ObjectTypeOutputFormat(objectTypeName, objectTypeDefinition)
|
|
427
|
+
|
|
428
|
+
else:
|
|
429
|
+
raise ValueError(
|
|
430
|
+
f"Invalid output format: '{outputValue}'. "
|
|
431
|
+
+ "Supported formats: 'json', 'jsonl', 'list_str', 'obj/TypeName'"
|
|
432
|
+
)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from abc import abstractmethod
|
|
2
|
+
from enum import Enum
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class SourceType(Enum):
|
|
6
|
+
SKILL = "SKILL"
|
|
7
|
+
LLM = "LLM"
|
|
8
|
+
EXPLORE = "EXPLORE"
|
|
9
|
+
ASSIGN = "ASSIGN"
|
|
10
|
+
LIST = "LIST"
|
|
11
|
+
OTHER = "OTHER"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Var:
|
|
15
|
+
def __init__(self, value):
|
|
16
|
+
self.val = value
|
|
17
|
+
|
|
18
|
+
@abstractmethod
|
|
19
|
+
def add(self, var: "Var") -> "Var":
|
|
20
|
+
raise NotImplementedError
|
|
21
|
+
|
|
22
|
+
@abstractmethod
|
|
23
|
+
def set_last(self, var: "Var") -> "Var":
|
|
24
|
+
raise NotImplementedError
|
|
25
|
+
|
|
26
|
+
@property
|
|
27
|
+
def value(self):
|
|
28
|
+
return self.val
|
|
29
|
+
|
|
30
|
+
def to_dict(self):
|
|
31
|
+
return self.val
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
# Note: ObjectType, ObjectTypeFactory, OutputFormat, etc. are available
|
|
35
|
+
# from dolphin.core.common.object_type and dolphin.core.common.output_format
|
|
36
|
+
# They are NOT re-exported here to avoid circular imports with enums.py
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""Config 模块 - 核心配置"""
|
|
3
|
+
|
|
4
|
+
from dolphin.core.config.global_config import GlobalConfig
|
|
5
|
+
from dolphin.core.config.ontology_config import (
|
|
6
|
+
DataSourceType,
|
|
7
|
+
DataSourceConfig,
|
|
8
|
+
OntologyConfig,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"GlobalConfig",
|
|
13
|
+
"DataSourceType",
|
|
14
|
+
"DataSourceConfig",
|
|
15
|
+
"OntologyConfig",
|
|
16
|
+
]
|