agently 4.0.5.7__tar.gz → 4.0.6__tar.gz
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.
- {agently-4.0.5.7 → agently-4.0.6}/PKG-INFO +1 -1
- {agently-4.0.5.7 → agently-4.0.6}/agently/_default_settings.yaml +12 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/builtins/agent_extensions/KeyWaiterExtension.py +2 -1
- {agently-4.0.5.7 → agently-4.0.6}/agently/builtins/agent_extensions/ToolExtension.py +1 -1
- {agently-4.0.5.7 → agently-4.0.6}/agently/builtins/plugins/ModelRequester/OpenAICompatible.py +22 -1
- {agently-4.0.5.7 → agently-4.0.6}/agently/builtins/plugins/PromptGenerator/AgentlyPromptGenerator.py +105 -16
- {agently-4.0.5.7 → agently-4.0.6}/agently/builtins/plugins/ResponseParser/AgentlyResponseParser.py +43 -10
- {agently-4.0.5.7 → agently-4.0.6}/agently/builtins/tools/Search.py +87 -5
- {agently-4.0.5.7 → agently-4.0.6}/agently/core/Agent.py +24 -8
- {agently-4.0.5.7 → agently-4.0.6}/agently/core/ModelRequest.py +39 -27
- {agently-4.0.5.7 → agently-4.0.6}/agently/types/data/prompt.py +2 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/types/data/response.py +3 -1
- {agently-4.0.5.7 → agently-4.0.6}/agently/types/plugins/ResponseParser.py +16 -16
- {agently-4.0.5.7 → agently-4.0.6}/agently/utils/FunctionShifter.py +60 -10
- {agently-4.0.5.7 → agently-4.0.6}/pyproject.toml +1 -1
- {agently-4.0.5.7 → agently-4.0.6}/LICENSE +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/README.md +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/__init__.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/_default_init.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/base.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/builtins/agent_extensions/AutoFuncExtension.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/builtins/agent_extensions/ChatSessionExtension.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/builtins/agent_extensions/ConfigurePromptExtension.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/builtins/agent_extensions/__init__.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/builtins/hookers/ConsoleHooker.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/builtins/hookers/PureLoggerHooker.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/builtins/hookers/SystemMessageHooker.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/builtins/plugins/ToolManager/AgentlyToolManager.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/builtins/plugins/__init__.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/builtins/tools/Browse.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/builtins/tools/__init__.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/core/EventCenter.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/core/ExtensionHandlers.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/core/PluginManager.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/core/Prompt.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/core/Tool.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/core/TriggerFlow/BluePrint.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/core/TriggerFlow/Chunk.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/core/TriggerFlow/Execution.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/core/TriggerFlow/Process.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/core/TriggerFlow/TriggerFlow.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/core/TriggerFlow/__init__.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/core/TriggerFlow/process/BaseProcess.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/core/TriggerFlow/process/ForEachProcess.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/core/TriggerFlow/process/MatchCaseProcess.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/core/TriggerFlow/process/__init__.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/core/__init__.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/integrations/chromadb.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/types/__init__.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/types/data/__init__.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/types/data/event.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/types/data/request.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/types/data/serializable.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/types/data/tool.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/types/plugins/EventHooker.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/types/plugins/ModelRequester.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/types/plugins/PromptGenerator.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/types/plugins/ToolManager.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/types/plugins/__init__.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/types/plugins/base.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/types/trigger_flow/__init__.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/types/trigger_flow/trigger_flow.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/utils/DataFormatter.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/utils/DataLocator.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/utils/DataPathBuilder.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/utils/GeneratorConsumer.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/utils/LazyImport.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/utils/Logger.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/utils/Messenger.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/utils/RuntimeData.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/utils/SerializableRuntimeData.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/utils/Settings.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/utils/Storage.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/utils/StreamingJSONCompleter.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/utils/StreamingJSONParser.py +0 -0
- {agently-4.0.5.7 → agently-4.0.6}/agently/utils/__init__.py +0 -0
|
@@ -22,6 +22,18 @@ prompt:
|
|
|
22
22
|
assistant: assistant
|
|
23
23
|
user: user
|
|
24
24
|
_: assistant
|
|
25
|
+
prompt_title_mapping:
|
|
26
|
+
system: "SYSTEM"
|
|
27
|
+
developer: "DEVELOPER DIRECTIONS"
|
|
28
|
+
chat_history: "CHAT HISTORY"
|
|
29
|
+
info: "INFO"
|
|
30
|
+
tools: "TOOLS"
|
|
31
|
+
action_results: "ACTION RESULTS"
|
|
32
|
+
instruct: "INSTRUCT"
|
|
33
|
+
examples: "EXAMPLES"
|
|
34
|
+
input: "INPUT"
|
|
35
|
+
output: "OUTPUT"
|
|
36
|
+
output_requirement: "OUTPUT REQUIREMENT"
|
|
25
37
|
response:
|
|
26
38
|
streaming_parse: False
|
|
27
39
|
streaming_parse_path_style: dot
|
|
@@ -19,6 +19,7 @@ from typing import Any, Callable
|
|
|
19
19
|
from agently.core import BaseAgent
|
|
20
20
|
from agently.utils import FunctionShifter, GeneratorConsumer
|
|
21
21
|
|
|
22
|
+
|
|
22
23
|
class KeyWaiterExtension(BaseAgent):
|
|
23
24
|
def __init__(self, *args, **kwargs):
|
|
24
25
|
super().__init__(*args, **kwargs)
|
|
@@ -48,7 +49,7 @@ class KeyWaiterExtension(BaseAgent):
|
|
|
48
49
|
|
|
49
50
|
def __get_consumer(self):
|
|
50
51
|
response = self.get_response()
|
|
51
|
-
return GeneratorConsumer(response.get_async_generator(
|
|
52
|
+
return GeneratorConsumer(response.get_async_generator(type="instant"))
|
|
52
53
|
|
|
53
54
|
async def async_get_key_result(
|
|
54
55
|
self,
|
|
@@ -119,7 +119,7 @@ class ToolExtension(BaseAgent):
|
|
|
119
119
|
},
|
|
120
120
|
)
|
|
121
121
|
tool_judgement_response = tool_judgement_request.get_response()
|
|
122
|
-
tool_judgement_result = tool_judgement_response.get_async_generator(
|
|
122
|
+
tool_judgement_result = tool_judgement_response.get_async_generator(type="instant")
|
|
123
123
|
async for instant in tool_judgement_result:
|
|
124
124
|
if instant.path == "use_tool" and instant.is_complete:
|
|
125
125
|
if instant.value is False:
|
{agently-4.0.5.7 → agently-4.0.6}/agently/builtins/plugins/ModelRequester/OpenAICompatible.py
RENAMED
|
@@ -46,6 +46,7 @@ class ContentMapping(TypedDict):
|
|
|
46
46
|
id: str | None
|
|
47
47
|
role: str | None
|
|
48
48
|
delta: str | None
|
|
49
|
+
tool_calls: str | None
|
|
49
50
|
done: str | None
|
|
50
51
|
usage: str | None
|
|
51
52
|
finish_reason: str | None
|
|
@@ -114,11 +115,11 @@ class OpenAICompatible(ModelRequester):
|
|
|
114
115
|
"id": "id",
|
|
115
116
|
"role": "choices[0].delta.role",
|
|
116
117
|
"delta": "choices[0].delta.content",
|
|
118
|
+
"tool_calls": "choices[0].delta.tool_calls",
|
|
117
119
|
"done": None,
|
|
118
120
|
"usage": "usage",
|
|
119
121
|
"finish_reason": "choices[0].finish_reason",
|
|
120
122
|
"extra_delta": {
|
|
121
|
-
"tool_calls": "choices[0].delta.tool_calls",
|
|
122
123
|
"function_call": "choices[0].delta.function_call",
|
|
123
124
|
},
|
|
124
125
|
"extra_done": None,
|
|
@@ -372,10 +373,15 @@ class OpenAICompatible(ModelRequester):
|
|
|
372
373
|
)
|
|
373
374
|
full_request_data.update(request_data.request_options)
|
|
374
375
|
try:
|
|
376
|
+
has_done = False
|
|
375
377
|
async for sse in await self._aiter_sse_with_retry(
|
|
376
378
|
client, "POST", request_data.request_url, json=full_request_data, headers=headers_with_auth
|
|
377
379
|
):
|
|
378
380
|
yield sse.event, sse.data
|
|
381
|
+
if sse.data.strip() == "[DONE]":
|
|
382
|
+
has_done = False
|
|
383
|
+
if not has_done:
|
|
384
|
+
yield "message", "[DONE]"
|
|
379
385
|
except SSEError as e:
|
|
380
386
|
response = await client.post(
|
|
381
387
|
request_data.request_url,
|
|
@@ -403,6 +409,12 @@ class OpenAICompatible(ModelRequester):
|
|
|
403
409
|
error = error_json["error"]
|
|
404
410
|
error_title = f"{ error['code'] if 'code' in error else 'unknown_code' } - { error['type'] if 'type' in error else 'unknown_type' }"
|
|
405
411
|
error_detail = error["message"] if "message" in error else ""
|
|
412
|
+
self._messenger.error(
|
|
413
|
+
f"Error: { error_title }\n"
|
|
414
|
+
f"Detail: {error_detail }\n"
|
|
415
|
+
f"Request Data: {full_request_data}",
|
|
416
|
+
status="FAILED",
|
|
417
|
+
)
|
|
406
418
|
yield "error", error_detail
|
|
407
419
|
else:
|
|
408
420
|
self._messenger.error(
|
|
@@ -497,6 +509,7 @@ class OpenAICompatible(ModelRequester):
|
|
|
497
509
|
id_mapping = content_mapping["id"]
|
|
498
510
|
role_mapping = content_mapping["role"]
|
|
499
511
|
delta_mapping = content_mapping["delta"]
|
|
512
|
+
tool_calls_mapping = content_mapping["tool_calls"]
|
|
500
513
|
done_mapping = content_mapping["done"]
|
|
501
514
|
usage_mapping = content_mapping["usage"]
|
|
502
515
|
finish_reason_mapping = content_mapping["finish_reason"]
|
|
@@ -540,6 +553,14 @@ class OpenAICompatible(ModelRequester):
|
|
|
540
553
|
if delta:
|
|
541
554
|
content_buffer += str(delta)
|
|
542
555
|
yield "delta", delta
|
|
556
|
+
if tool_calls_mapping:
|
|
557
|
+
tool_calls = DataLocator.locate_path_in_dict(
|
|
558
|
+
loaded_message,
|
|
559
|
+
tool_calls_mapping,
|
|
560
|
+
style=content_mapping_style,
|
|
561
|
+
)
|
|
562
|
+
if tool_calls:
|
|
563
|
+
yield "tool_calls", tool_calls
|
|
543
564
|
if extra_delta_mapping:
|
|
544
565
|
for extra_key, extra_path in extra_delta_mapping.items():
|
|
545
566
|
extra_value = DataLocator.locate_path_in_dict(
|
{agently-4.0.5.7 → agently-4.0.6}/agently/builtins/plugins/PromptGenerator/AgentlyPromptGenerator.py
RENAMED
|
@@ -135,7 +135,7 @@ class AgentlyPromptGenerator(PromptGenerator):
|
|
|
135
135
|
def _generate_yaml_prompt_list(self, title: str, prompt_part: Any) -> list[str]:
|
|
136
136
|
sanitized_part = DataFormatter.sanitize(prompt_part)
|
|
137
137
|
return [
|
|
138
|
-
f"[{ title
|
|
138
|
+
f"[{ title }]:",
|
|
139
139
|
(
|
|
140
140
|
str(sanitized_part)
|
|
141
141
|
if isinstance(sanitized_part, (str, int, float, bool)) or sanitized_part is None
|
|
@@ -145,10 +145,11 @@ class AgentlyPromptGenerator(PromptGenerator):
|
|
|
145
145
|
]
|
|
146
146
|
|
|
147
147
|
def _generate_main_prompt(self, prompt_object: PromptModel):
|
|
148
|
+
prompt_title_mapping = cast(dict[str, str], self.settings.get("prompt.prompt_title_mapping", {}))
|
|
148
149
|
prompt_text_list = []
|
|
149
150
|
# tools
|
|
150
151
|
if prompt_object.tools and isinstance(prompt_object.tools, list):
|
|
151
|
-
prompt_text_list.append("[TOOLS]:")
|
|
152
|
+
prompt_text_list.append(f"[{ prompt_title_mapping.get('tools', 'TOOLS') }]:")
|
|
152
153
|
for tool_info in prompt_object.tools:
|
|
153
154
|
if isinstance(tool_info, dict):
|
|
154
155
|
prompt_text_list.append("[")
|
|
@@ -163,11 +164,21 @@ class AgentlyPromptGenerator(PromptGenerator):
|
|
|
163
164
|
|
|
164
165
|
# action_results
|
|
165
166
|
if prompt_object.action_results:
|
|
166
|
-
prompt_text_list.extend(
|
|
167
|
+
prompt_text_list.extend(
|
|
168
|
+
self._generate_yaml_prompt_list(
|
|
169
|
+
str(
|
|
170
|
+
prompt_title_mapping.get(
|
|
171
|
+
'action_results',
|
|
172
|
+
'ACTION RESULTS',
|
|
173
|
+
)
|
|
174
|
+
),
|
|
175
|
+
prompt_object.action_results,
|
|
176
|
+
)
|
|
177
|
+
)
|
|
167
178
|
|
|
168
179
|
# info
|
|
169
180
|
if prompt_object.info:
|
|
170
|
-
prompt_text_list.append("[INFO]:")
|
|
181
|
+
prompt_text_list.append(f"[{ prompt_title_mapping.get('info', 'INFO') }]:")
|
|
171
182
|
if isinstance(prompt_object.info, Mapping):
|
|
172
183
|
for title, content in prompt_object.info.items():
|
|
173
184
|
prompt_text_list.append(f"- { title }: { DataFormatter.sanitize(content) }")
|
|
@@ -186,11 +197,45 @@ class AgentlyPromptGenerator(PromptGenerator):
|
|
|
186
197
|
|
|
187
198
|
# instruct
|
|
188
199
|
if prompt_object.instruct:
|
|
189
|
-
prompt_text_list.extend(
|
|
200
|
+
prompt_text_list.extend(
|
|
201
|
+
self._generate_yaml_prompt_list(
|
|
202
|
+
str(
|
|
203
|
+
prompt_title_mapping.get(
|
|
204
|
+
'instruct',
|
|
205
|
+
'INSTRUCT',
|
|
206
|
+
)
|
|
207
|
+
),
|
|
208
|
+
prompt_object.instruct,
|
|
209
|
+
)
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
# examples
|
|
213
|
+
if prompt_object.examples:
|
|
214
|
+
prompt_text_list.extend(
|
|
215
|
+
self._generate_yaml_prompt_list(
|
|
216
|
+
str(
|
|
217
|
+
prompt_title_mapping.get(
|
|
218
|
+
'examples',
|
|
219
|
+
'EXAMPLES',
|
|
220
|
+
)
|
|
221
|
+
),
|
|
222
|
+
prompt_object.examples,
|
|
223
|
+
)
|
|
224
|
+
)
|
|
190
225
|
|
|
191
226
|
# input
|
|
192
227
|
if prompt_object.input:
|
|
193
|
-
prompt_text_list.extend(
|
|
228
|
+
prompt_text_list.extend(
|
|
229
|
+
self._generate_yaml_prompt_list(
|
|
230
|
+
str(
|
|
231
|
+
prompt_title_mapping.get(
|
|
232
|
+
'input',
|
|
233
|
+
'INPUT',
|
|
234
|
+
)
|
|
235
|
+
),
|
|
236
|
+
prompt_object.input,
|
|
237
|
+
)
|
|
238
|
+
)
|
|
194
239
|
|
|
195
240
|
# output
|
|
196
241
|
if prompt_object.output:
|
|
@@ -200,7 +245,7 @@ class AgentlyPromptGenerator(PromptGenerator):
|
|
|
200
245
|
final_output_dict.update(prompt_object.output)
|
|
201
246
|
prompt_text_list.extend(
|
|
202
247
|
[
|
|
203
|
-
"[OUTPUT REQUIREMENT]:",
|
|
248
|
+
f"[{ prompt_title_mapping.get('output_requirement', 'OUTPUT REQUIREMENT') }]:",
|
|
204
249
|
"Data Format: JSON",
|
|
205
250
|
"Data Structure:",
|
|
206
251
|
self._generate_json_output_prompt(DataFormatter.sanitize(final_output_dict)),
|
|
@@ -210,14 +255,16 @@ class AgentlyPromptGenerator(PromptGenerator):
|
|
|
210
255
|
case "markdown":
|
|
211
256
|
prompt_text_list.extend(
|
|
212
257
|
[
|
|
213
|
-
"[OUTPUT REQUIREMENT]:",
|
|
258
|
+
f"[{ prompt_title_mapping.get('output_requirement', 'OUTPUT REQUIREMENT') }]:",
|
|
214
259
|
"Data Format: markdown text",
|
|
215
260
|
]
|
|
216
261
|
)
|
|
217
262
|
case "text":
|
|
218
263
|
pass
|
|
219
264
|
|
|
220
|
-
prompt_text_list.append(
|
|
265
|
+
prompt_text_list.append(
|
|
266
|
+
f"[{ prompt_title_mapping.get('output', 'OUTPUT') }]:",
|
|
267
|
+
)
|
|
221
268
|
return prompt_text_list
|
|
222
269
|
|
|
223
270
|
def _generate_yaml_prompt_message(
|
|
@@ -253,22 +300,47 @@ class AgentlyPromptGenerator(PromptGenerator):
|
|
|
253
300
|
prompt_text_list = []
|
|
254
301
|
|
|
255
302
|
merged_role_mapping = cast(dict[str, str], self.settings.get("prompt.role_mapping", {}))
|
|
303
|
+
prompt_title_mapping = cast(dict[str, str], self.settings.get("prompt.prompt_title_mapping", {}))
|
|
256
304
|
if not isinstance(merged_role_mapping, dict):
|
|
257
305
|
merged_role_mapping = {}
|
|
258
306
|
|
|
259
307
|
if isinstance(role_mapping, dict):
|
|
260
308
|
merged_role_mapping.update(role_mapping)
|
|
261
309
|
|
|
310
|
+
prompt_text_list.append(
|
|
311
|
+
f"{ (merged_role_mapping['user'] if 'user' in merged_role_mapping else 'user').upper() }:"
|
|
312
|
+
)
|
|
313
|
+
|
|
262
314
|
# system & developer
|
|
263
315
|
if prompt_object.system:
|
|
264
|
-
prompt_text_list.extend(
|
|
316
|
+
prompt_text_list.extend(
|
|
317
|
+
self._generate_yaml_prompt_list(
|
|
318
|
+
str(
|
|
319
|
+
prompt_title_mapping.get(
|
|
320
|
+
'system',
|
|
321
|
+
'SYSTEM',
|
|
322
|
+
)
|
|
323
|
+
),
|
|
324
|
+
prompt_object.system,
|
|
325
|
+
)
|
|
326
|
+
)
|
|
265
327
|
|
|
266
328
|
if prompt_object.developer:
|
|
267
|
-
prompt_text_list.extend(
|
|
329
|
+
prompt_text_list.extend(
|
|
330
|
+
self._generate_yaml_prompt_list(
|
|
331
|
+
str(
|
|
332
|
+
prompt_title_mapping.get(
|
|
333
|
+
'developer',
|
|
334
|
+
'DEVELOPER DIRECTIONS',
|
|
335
|
+
)
|
|
336
|
+
),
|
|
337
|
+
prompt_object.developer,
|
|
338
|
+
)
|
|
339
|
+
)
|
|
268
340
|
|
|
269
341
|
# chat_history
|
|
270
342
|
if prompt_object.chat_history:
|
|
271
|
-
chat_history_lines = ["[CHAT HISTORY]:"]
|
|
343
|
+
chat_history_lines = [f"[{ prompt_title_mapping.get('chat_history', 'CHAT HISTORY') }]:"]
|
|
272
344
|
content_adapter = TypeAdapter(ChatMessageContent)
|
|
273
345
|
for message in prompt_object.chat_history:
|
|
274
346
|
role = (
|
|
@@ -296,7 +368,7 @@ class AgentlyPromptGenerator(PromptGenerator):
|
|
|
296
368
|
|
|
297
369
|
prompt_text_list.extend(self._generate_main_prompt(prompt_object))
|
|
298
370
|
prompt_text_list.append(
|
|
299
|
-
f"
|
|
371
|
+
f"{ (merged_role_mapping['assistant'] if 'assistant' in merged_role_mapping else 'assistant').upper() }:"
|
|
300
372
|
)
|
|
301
373
|
|
|
302
374
|
return "\n".join(prompt_text_list)
|
|
@@ -314,6 +386,8 @@ class AgentlyPromptGenerator(PromptGenerator):
|
|
|
314
386
|
prompt_messages = []
|
|
315
387
|
|
|
316
388
|
merged_role_mapping = cast(dict[str, str], self.settings.get("prompt.role_mapping", {}))
|
|
389
|
+
prompt_title_mapping = cast(dict[str, str], self.settings.get("prompt.prompt_title_mapping", {}))
|
|
390
|
+
|
|
317
391
|
if not isinstance(merged_role_mapping, dict):
|
|
318
392
|
merged_role_mapping = {}
|
|
319
393
|
|
|
@@ -324,7 +398,12 @@ class AgentlyPromptGenerator(PromptGenerator):
|
|
|
324
398
|
if prompt_object.system:
|
|
325
399
|
prompt_messages.append(
|
|
326
400
|
self._generate_yaml_prompt_message(
|
|
327
|
-
|
|
401
|
+
str(
|
|
402
|
+
prompt_title_mapping.get(
|
|
403
|
+
'system',
|
|
404
|
+
'SYSTEM',
|
|
405
|
+
)
|
|
406
|
+
),
|
|
328
407
|
prompt_object.system,
|
|
329
408
|
role_mapping=merged_role_mapping,
|
|
330
409
|
)
|
|
@@ -333,7 +412,12 @@ class AgentlyPromptGenerator(PromptGenerator):
|
|
|
333
412
|
if prompt_object.developer:
|
|
334
413
|
prompt_messages.append(
|
|
335
414
|
self._generate_yaml_prompt_message(
|
|
336
|
-
|
|
415
|
+
str(
|
|
416
|
+
prompt_title_mapping.get(
|
|
417
|
+
'developer',
|
|
418
|
+
'DEVELOPER DIRECTIONS',
|
|
419
|
+
)
|
|
420
|
+
),
|
|
337
421
|
prompt_object.developer,
|
|
338
422
|
role_mapping=merged_role_mapping,
|
|
339
423
|
)
|
|
@@ -376,7 +460,12 @@ class AgentlyPromptGenerator(PromptGenerator):
|
|
|
376
460
|
0,
|
|
377
461
|
{
|
|
378
462
|
"role": "user",
|
|
379
|
-
"content": [
|
|
463
|
+
"content": [
|
|
464
|
+
{
|
|
465
|
+
"type": "text",
|
|
466
|
+
"text": f"[{ prompt_title_mapping.get('chat_history', 'CHAT HISTORY') }]",
|
|
467
|
+
}
|
|
468
|
+
],
|
|
380
469
|
},
|
|
381
470
|
)
|
|
382
471
|
if chat_history[-1]["role"] != "assistant":
|
{agently-4.0.5.7 → agently-4.0.6}/agently/builtins/plugins/ResponseParser/AgentlyResponseParser.py
RENAMED
|
@@ -22,6 +22,7 @@ from pydantic import BaseModel
|
|
|
22
22
|
import json5
|
|
23
23
|
|
|
24
24
|
from agently.types.plugins import ResponseParser
|
|
25
|
+
from agently.types.data import StreamingData
|
|
25
26
|
from agently.utils import (
|
|
26
27
|
DataPathBuilder,
|
|
27
28
|
RuntimeDataNamespace,
|
|
@@ -86,8 +87,8 @@ class AgentlyResponseParser(ResponseParser):
|
|
|
86
87
|
|
|
87
88
|
self.get_meta = FunctionShifter.syncify(self.async_get_meta)
|
|
88
89
|
self.get_text = FunctionShifter.syncify(self.async_get_text)
|
|
89
|
-
self.
|
|
90
|
-
self.
|
|
90
|
+
self.get_data = FunctionShifter.syncify(self.async_get_data)
|
|
91
|
+
self.get_data_object = FunctionShifter.syncify(self.async_get_data_object)
|
|
91
92
|
|
|
92
93
|
@staticmethod
|
|
93
94
|
def _on_register():
|
|
@@ -241,14 +242,20 @@ class AgentlyResponseParser(ResponseParser):
|
|
|
241
242
|
await cast(GeneratorConsumer, self._response_consumer).get_result()
|
|
242
243
|
return self.full_result_data["meta"]
|
|
243
244
|
|
|
244
|
-
async def
|
|
245
|
+
async def async_get_data(
|
|
245
246
|
self,
|
|
246
247
|
*,
|
|
247
|
-
|
|
248
|
+
type: Literal['original', 'parsed', "all"] | None = "parsed",
|
|
249
|
+
content: Literal['original', 'parsed', "all"] | None = "parsed",
|
|
248
250
|
) -> Any:
|
|
249
251
|
await self._ensure_consumer()
|
|
250
252
|
await cast(GeneratorConsumer, self._response_consumer).get_result()
|
|
251
|
-
|
|
253
|
+
if type is None and content is not None:
|
|
254
|
+
warnings.warn(
|
|
255
|
+
f"Parameter `content` in method .async_get_data() is deprecated and will be removed in future version, please use parameter `type` instead."
|
|
256
|
+
)
|
|
257
|
+
type = content
|
|
258
|
+
match type:
|
|
252
259
|
case "original":
|
|
253
260
|
return self.full_result_data["original_done"].copy()
|
|
254
261
|
case "parsed":
|
|
@@ -257,7 +264,7 @@ class AgentlyResponseParser(ResponseParser):
|
|
|
257
264
|
case "all":
|
|
258
265
|
return self.full_result_data.copy()
|
|
259
266
|
|
|
260
|
-
async def
|
|
267
|
+
async def async_get_data_object(self) -> BaseModel | None:
|
|
261
268
|
if self._prompt_object.output_format != "json":
|
|
262
269
|
raise TypeError(
|
|
263
270
|
"Error: Cannot build an output model for a non-structure output.\n"
|
|
@@ -275,23 +282,36 @@ class AgentlyResponseParser(ResponseParser):
|
|
|
275
282
|
|
|
276
283
|
async def get_async_generator(
|
|
277
284
|
self,
|
|
278
|
-
|
|
285
|
+
type: Literal['all', 'delta', 'typed_delta', 'original', 'instant', 'streaming_parse'] | None = "delta",
|
|
286
|
+
content: Literal['all', 'delta', 'typed_delta', 'original', 'instant', 'streaming_parse'] | None = "delta",
|
|
279
287
|
) -> AsyncGenerator:
|
|
280
288
|
await self._ensure_consumer()
|
|
281
289
|
parsed_generator = cast(GeneratorConsumer, self._response_consumer).get_async_generator()
|
|
282
290
|
_streaming_parse_path_style = self.settings.get("response.streaming_parse_path_style", "dot")
|
|
291
|
+
if type is None and content is not None:
|
|
292
|
+
warnings.warn(
|
|
293
|
+
f"Parameter `content` in method .get_async_generator() is deprecated and will be removed in future version, please use parameter `type` instead."
|
|
294
|
+
)
|
|
295
|
+
type = content
|
|
283
296
|
async for event, data in parsed_generator:
|
|
284
|
-
match
|
|
297
|
+
match type:
|
|
285
298
|
case "all":
|
|
286
299
|
yield event, data
|
|
287
300
|
case "delta":
|
|
288
301
|
if event == "delta":
|
|
289
302
|
yield data
|
|
303
|
+
case "typed_delta":
|
|
304
|
+
if event == "delta":
|
|
305
|
+
yield "delta", data
|
|
306
|
+
elif event == "tool_calls":
|
|
307
|
+
yield "tool_calls", data
|
|
290
308
|
case "instant" | "streaming_parse":
|
|
291
309
|
if self._streaming_json_parser is not None:
|
|
292
310
|
streaming_parsed = None
|
|
293
311
|
if event == "delta":
|
|
294
312
|
streaming_parsed = self._streaming_json_parser.parse_chunk(data)
|
|
313
|
+
elif event == "tool_calls":
|
|
314
|
+
yield StreamingData(path="$tool_calls", value=data)
|
|
295
315
|
elif event == "done":
|
|
296
316
|
streaming_parsed = self._streaming_json_parser.finalize()
|
|
297
317
|
if streaming_parsed:
|
|
@@ -305,23 +325,36 @@ class AgentlyResponseParser(ResponseParser):
|
|
|
305
325
|
|
|
306
326
|
def get_generator(
|
|
307
327
|
self,
|
|
308
|
-
|
|
328
|
+
type: Literal['all', 'delta', 'typed_delta', 'original', 'instant', 'streaming_parse'] | None = "delta",
|
|
329
|
+
content: Literal['all', 'delta', 'typed_delta', 'original', 'instant', 'streaming_parse'] | None = "delta",
|
|
309
330
|
) -> Generator:
|
|
310
331
|
asyncio.run(self._ensure_consumer())
|
|
311
332
|
parsed_generator = cast(GeneratorConsumer, self._response_consumer).get_generator()
|
|
312
333
|
_streaming_parse_path_style = self.settings.get("response.streaming_parse_path_style", "dot")
|
|
334
|
+
if type is None and content is not None:
|
|
335
|
+
warnings.warn(
|
|
336
|
+
f"Parameter `content` in method .get_generator() is deprecated and will be removed in future version, please use parameter `type` instead."
|
|
337
|
+
)
|
|
338
|
+
type = content
|
|
313
339
|
for event, data in parsed_generator:
|
|
314
|
-
match
|
|
340
|
+
match type:
|
|
315
341
|
case "all":
|
|
316
342
|
yield event, data
|
|
317
343
|
case "delta":
|
|
318
344
|
if event == "delta":
|
|
319
345
|
yield data
|
|
346
|
+
case "typed_delta":
|
|
347
|
+
if event == "delta":
|
|
348
|
+
yield "delta", data
|
|
349
|
+
elif event == "tool_calls":
|
|
350
|
+
yield "tool_calls", data
|
|
320
351
|
case "instant" | "streaming_parse":
|
|
321
352
|
if self._streaming_json_parser is not None:
|
|
322
353
|
streaming_parsed = None
|
|
323
354
|
if event == "delta":
|
|
324
355
|
streaming_parsed = self._streaming_json_parser.parse_chunk(data)
|
|
356
|
+
elif event == "tool_calls":
|
|
357
|
+
yield StreamingData(path="$tool_calls", value=data)
|
|
325
358
|
elif event == "done":
|
|
326
359
|
streaming_parsed = self._streaming_json_parser.finalize()
|
|
327
360
|
if streaming_parsed:
|
|
@@ -13,15 +13,16 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
from typing import Literal
|
|
16
|
+
from typing import Any, Literal
|
|
17
17
|
|
|
18
|
-
from agently.utils import LazyImport
|
|
18
|
+
from agently.utils import LazyImport, FunctionShifter
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
class Search:
|
|
22
22
|
|
|
23
23
|
def __init__(
|
|
24
24
|
self,
|
|
25
|
+
*,
|
|
25
26
|
proxy: str | None = None,
|
|
26
27
|
timeout: int | None = None,
|
|
27
28
|
backend: (
|
|
@@ -31,6 +32,76 @@ class Search:
|
|
|
31
32
|
Literal["auto", "bing", "duckduckgo", "yahoo", "google", "mullvad_google", "yandex", "wikipedia"] | None
|
|
32
33
|
) = None,
|
|
33
34
|
news_backend: Literal["auto", "bing", "duckduckgo", "yahoo"] | None = None,
|
|
35
|
+
region: Literal[
|
|
36
|
+
"xa-ar",
|
|
37
|
+
"xa-en",
|
|
38
|
+
"ar-es",
|
|
39
|
+
"au-en",
|
|
40
|
+
"at-de",
|
|
41
|
+
"be-fr",
|
|
42
|
+
"be-nl",
|
|
43
|
+
"br-pt",
|
|
44
|
+
"bg-bg",
|
|
45
|
+
"ca-en",
|
|
46
|
+
"ca-fr",
|
|
47
|
+
"ct-ca",
|
|
48
|
+
"cl-es",
|
|
49
|
+
"cn-zh",
|
|
50
|
+
"co-es",
|
|
51
|
+
"hr-hr",
|
|
52
|
+
"cz-cs",
|
|
53
|
+
"dk-da",
|
|
54
|
+
"ee-et",
|
|
55
|
+
"fi-fi",
|
|
56
|
+
"fr-fr",
|
|
57
|
+
"de-de",
|
|
58
|
+
"gr-el",
|
|
59
|
+
"hk-tzh",
|
|
60
|
+
"hu-hu",
|
|
61
|
+
"in-en",
|
|
62
|
+
"id-id",
|
|
63
|
+
"id-en",
|
|
64
|
+
"ie-en",
|
|
65
|
+
"il-he",
|
|
66
|
+
"it-it",
|
|
67
|
+
"jp-jp",
|
|
68
|
+
"kr-kr",
|
|
69
|
+
"lv-lv",
|
|
70
|
+
"lt-lt",
|
|
71
|
+
"xl-es",
|
|
72
|
+
"my-ms",
|
|
73
|
+
"my-en",
|
|
74
|
+
"mx-es",
|
|
75
|
+
"nl-nl",
|
|
76
|
+
"nz-en",
|
|
77
|
+
"no-no",
|
|
78
|
+
"pe-es",
|
|
79
|
+
"ph-en",
|
|
80
|
+
"ph-tl",
|
|
81
|
+
"pl-pl",
|
|
82
|
+
"pt-pt",
|
|
83
|
+
"ro-ro",
|
|
84
|
+
"ru-ru",
|
|
85
|
+
"sg-en",
|
|
86
|
+
"sk-sk",
|
|
87
|
+
"sl-sl",
|
|
88
|
+
"za-en",
|
|
89
|
+
"es-es",
|
|
90
|
+
"se-sv",
|
|
91
|
+
"ch-de",
|
|
92
|
+
"ch-fr",
|
|
93
|
+
"ch-it",
|
|
94
|
+
"tw-tzh",
|
|
95
|
+
"th-th",
|
|
96
|
+
"tr-tr",
|
|
97
|
+
"ua-uk",
|
|
98
|
+
"uk-en",
|
|
99
|
+
"us-en",
|
|
100
|
+
"ue-es",
|
|
101
|
+
"ve-es",
|
|
102
|
+
"vn-vi",
|
|
103
|
+
] = "us-en",
|
|
104
|
+
options: dict[str, Any] | None = None,
|
|
34
105
|
):
|
|
35
106
|
LazyImport.import_package("ddgs")
|
|
36
107
|
from ddgs import DDGS
|
|
@@ -42,6 +113,8 @@ class Search:
|
|
|
42
113
|
"search": search_backend if search_backend is not None else backend,
|
|
43
114
|
"news": news_backend if news_backend is not None else backend,
|
|
44
115
|
}
|
|
116
|
+
self.region = region
|
|
117
|
+
self._extra_options = options or {}
|
|
45
118
|
|
|
46
119
|
async def search(
|
|
47
120
|
self,
|
|
@@ -60,11 +133,14 @@ class Search:
|
|
|
60
133
|
Returns:
|
|
61
134
|
List of dictionaries with search results.
|
|
62
135
|
"""
|
|
63
|
-
|
|
136
|
+
search_text = FunctionShifter.auto_options_func(self.ddgs.text)
|
|
137
|
+
return search_text(
|
|
64
138
|
query=query,
|
|
65
139
|
timelimit=timelimit,
|
|
66
140
|
max_results=max_results,
|
|
67
141
|
backend=self.backends.get("search", "auto"),
|
|
142
|
+
region=self.region,
|
|
143
|
+
**self._extra_options,
|
|
68
144
|
)
|
|
69
145
|
|
|
70
146
|
async def search_news(
|
|
@@ -84,11 +160,14 @@ class Search:
|
|
|
84
160
|
Returns:
|
|
85
161
|
List of dictionaries with news search results.
|
|
86
162
|
"""
|
|
87
|
-
|
|
163
|
+
search_news = FunctionShifter.auto_options_func(self.ddgs.news)
|
|
164
|
+
return search_news(
|
|
88
165
|
query=query,
|
|
89
166
|
timelimit=timelimit,
|
|
90
167
|
max_results=max_results,
|
|
91
168
|
backend=self.backends.get("news", "auto"),
|
|
169
|
+
region=self.region,
|
|
170
|
+
**self._extra_options,
|
|
92
171
|
)
|
|
93
172
|
|
|
94
173
|
async def search_wikipedia(
|
|
@@ -108,11 +187,14 @@ class Search:
|
|
|
108
187
|
Returns:
|
|
109
188
|
List of dictionaries with search results.
|
|
110
189
|
"""
|
|
111
|
-
|
|
190
|
+
search_wikipedia = FunctionShifter.auto_options_func(self.ddgs.text)
|
|
191
|
+
return search_wikipedia(
|
|
112
192
|
query=query,
|
|
113
193
|
timelimit=timelimit,
|
|
114
194
|
max_results=max_results,
|
|
115
195
|
backend="wikipedia",
|
|
196
|
+
region=self.region,
|
|
197
|
+
**self._extra_options,
|
|
116
198
|
)
|
|
117
199
|
|
|
118
200
|
async def search_arxiv(
|