agently 4.0.5.8__py3-none-any.whl → 4.0.6.1__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.
- agently/_default_settings.yaml +12 -0
- agently/builtins/agent_extensions/KeyWaiterExtension.py +2 -1
- agently/builtins/agent_extensions/ToolExtension.py +1 -1
- agently/builtins/plugins/ModelRequester/OpenAICompatible.py +11 -1
- agently/builtins/plugins/PromptGenerator/AgentlyPromptGenerator.py +105 -16
- agently/builtins/plugins/ResponseParser/AgentlyResponseParser.py +43 -10
- agently/builtins/tools/Search.py +87 -5
- agently/core/Agent.py +24 -8
- agently/core/ModelRequest.py +39 -27
- agently/types/data/prompt.py +2 -0
- agently/types/data/response.py +3 -1
- agently/types/plugins/ResponseParser.py +16 -16
- agently/utils/FunctionShifter.py +60 -10
- agently/utils/Storage.py +8 -3
- {agently-4.0.5.8.dist-info → agently-4.0.6.1.dist-info}/METADATA +2 -2
- {agently-4.0.5.8.dist-info → agently-4.0.6.1.dist-info}/RECORD +18 -18
- {agently-4.0.5.8.dist-info → agently-4.0.6.1.dist-info}/WHEEL +0 -0
- {agently-4.0.5.8.dist-info → agently-4.0.6.1.dist-info}/licenses/LICENSE +0 -0
agently/_default_settings.yaml
CHANGED
|
@@ -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:
|
|
@@ -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,
|
|
@@ -508,6 +509,7 @@ class OpenAICompatible(ModelRequester):
|
|
|
508
509
|
id_mapping = content_mapping["id"]
|
|
509
510
|
role_mapping = content_mapping["role"]
|
|
510
511
|
delta_mapping = content_mapping["delta"]
|
|
512
|
+
tool_calls_mapping = content_mapping["tool_calls"]
|
|
511
513
|
done_mapping = content_mapping["done"]
|
|
512
514
|
usage_mapping = content_mapping["usage"]
|
|
513
515
|
finish_reason_mapping = content_mapping["finish_reason"]
|
|
@@ -551,6 +553,14 @@ class OpenAICompatible(ModelRequester):
|
|
|
551
553
|
if delta:
|
|
552
554
|
content_buffer += str(delta)
|
|
553
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
|
|
554
564
|
if extra_delta_mapping:
|
|
555
565
|
for extra_key, extra_path in extra_delta_mapping.items():
|
|
556
566
|
extra_value = DataLocator.locate_path_in_dict(
|
|
@@ -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":
|
|
@@ -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:
|
agently/builtins/tools/Search.py
CHANGED
|
@@ -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(
|
agently/core/Agent.py
CHANGED
|
@@ -40,7 +40,7 @@ class BaseAgent:
|
|
|
40
40
|
name=f"Agent-{ self.name }-Settings",
|
|
41
41
|
parent=parent_settings,
|
|
42
42
|
)
|
|
43
|
-
self.
|
|
43
|
+
self.agent_prompt = Prompt(
|
|
44
44
|
name=f"Agent-{ self.name }-Prompt",
|
|
45
45
|
plugin_manager=self.plugin_manager,
|
|
46
46
|
parent_settings=self.settings,
|
|
@@ -58,24 +58,27 @@ class BaseAgent:
|
|
|
58
58
|
agent_name=self.name,
|
|
59
59
|
plugin_manager=self.plugin_manager,
|
|
60
60
|
parent_settings=self.settings,
|
|
61
|
-
parent_prompt=self.
|
|
61
|
+
parent_prompt=self.agent_prompt,
|
|
62
62
|
parent_extension_handlers=self.extension_handlers,
|
|
63
63
|
)
|
|
64
|
+
self.request_prompt = self.request.prompt
|
|
65
|
+
self.prompt = self.request_prompt
|
|
64
66
|
|
|
65
67
|
self.get_response = self.request.get_response
|
|
68
|
+
self.get_result = self.request.get_result
|
|
66
69
|
self.get_meta = self.request.get_meta
|
|
67
70
|
self.async_get_meta = self.request.async_get_meta
|
|
68
71
|
self.get_text = self.request.get_text
|
|
69
72
|
self.async_get_text = self.request.async_get_text
|
|
70
|
-
self.
|
|
71
|
-
self.
|
|
72
|
-
self.
|
|
73
|
-
self.
|
|
73
|
+
self.get_data = self.request.get_data
|
|
74
|
+
self.async_get_data = self.request.async_get_data
|
|
75
|
+
self.get_data_object = self.request.get_data_object
|
|
76
|
+
self.async_get_data_object = self.request.async_get_data_object
|
|
74
77
|
self.get_generator = self.request.get_generator
|
|
75
78
|
self.get_async_generator = self.request.get_async_generator
|
|
76
79
|
|
|
77
|
-
self.start = self.
|
|
78
|
-
self.async_start = self.
|
|
80
|
+
self.start = self.get_data
|
|
81
|
+
self.async_start = self.async_get_data
|
|
79
82
|
|
|
80
83
|
# Basic Methods
|
|
81
84
|
def set_settings(self, key: str, value: "SerializableValue"):
|
|
@@ -237,6 +240,19 @@ class BaseAgent:
|
|
|
237
240
|
self.request.prompt.set("instruct", prompt, mappings)
|
|
238
241
|
return self
|
|
239
242
|
|
|
243
|
+
def examples(
|
|
244
|
+
self,
|
|
245
|
+
prompt: Any,
|
|
246
|
+
mappings: dict[str, Any] | None = None,
|
|
247
|
+
*,
|
|
248
|
+
always: bool = False,
|
|
249
|
+
):
|
|
250
|
+
if always:
|
|
251
|
+
self.prompt.set("examples", prompt, mappings)
|
|
252
|
+
else:
|
|
253
|
+
self.request.prompt.set("examples", prompt, mappings)
|
|
254
|
+
return self
|
|
255
|
+
|
|
240
256
|
def output(
|
|
241
257
|
self,
|
|
242
258
|
prompt: (
|
agently/core/ModelRequest.py
CHANGED
|
@@ -57,10 +57,10 @@ class ModelResponseResult:
|
|
|
57
57
|
self.async_get_meta = _response_parser.async_get_meta
|
|
58
58
|
self.get_text = _response_parser.get_text
|
|
59
59
|
self.async_get_text = _response_parser.async_get_text
|
|
60
|
-
self.
|
|
61
|
-
self.
|
|
62
|
-
self.
|
|
63
|
-
self.
|
|
60
|
+
self.get_data = _response_parser.get_data
|
|
61
|
+
self.async_get_data = _response_parser.async_get_data
|
|
62
|
+
self.get_data_object = _response_parser.get_data_object
|
|
63
|
+
self.async_get_data_object = _response_parser.async_get_data_object
|
|
64
64
|
self.get_generator = _response_parser.get_generator
|
|
65
65
|
self.get_async_generator = _response_parser.get_async_generator
|
|
66
66
|
|
|
@@ -99,14 +99,15 @@ class ModelResponse:
|
|
|
99
99
|
self.plugin_manager,
|
|
100
100
|
self.settings,
|
|
101
101
|
)
|
|
102
|
+
self.get_result = self.result
|
|
102
103
|
self.get_meta = self.result.get_meta
|
|
103
104
|
self.async_get_meta = self.result.async_get_meta
|
|
104
105
|
self.get_text = self.result.get_text
|
|
105
106
|
self.async_get_text = self.result.async_get_text
|
|
106
|
-
self.
|
|
107
|
-
self.
|
|
108
|
-
self.
|
|
109
|
-
self.
|
|
107
|
+
self.get_data = self.result.get_data
|
|
108
|
+
self.async_get_data = self.result.async_get_data
|
|
109
|
+
self.get_data_object = self.result.get_data_object
|
|
110
|
+
self.async_get_data_object = self.result.async_get_data_object
|
|
110
111
|
self.get_generator = self.result.get_generator
|
|
111
112
|
self.get_async_generator = self.result.get_async_generator
|
|
112
113
|
|
|
@@ -298,8 +299,8 @@ class ModelRequest:
|
|
|
298
299
|
|
|
299
300
|
self.get_meta = FunctionShifter.syncify(self.async_get_meta)
|
|
300
301
|
self.get_text = FunctionShifter.syncify(self.async_get_text)
|
|
301
|
-
self.
|
|
302
|
-
self.
|
|
302
|
+
self.get_data = FunctionShifter.syncify(self.async_get_data)
|
|
303
|
+
self.get_data_object = FunctionShifter.syncify(self.async_get_data_object)
|
|
303
304
|
|
|
304
305
|
def set_settings(self, key: str, value: "SerializableValue"):
|
|
305
306
|
self.settings.set_settings(key, value)
|
|
@@ -373,6 +374,14 @@ class ModelRequest:
|
|
|
373
374
|
self.prompt.set("instruct", prompt, mappings)
|
|
374
375
|
return self
|
|
375
376
|
|
|
377
|
+
def examples(
|
|
378
|
+
self,
|
|
379
|
+
prompt: Any,
|
|
380
|
+
mappings: dict[str, Any] | None = None,
|
|
381
|
+
):
|
|
382
|
+
self.prompt.set("examples", prompt, mappings)
|
|
383
|
+
return self
|
|
384
|
+
|
|
376
385
|
def output(
|
|
377
386
|
self,
|
|
378
387
|
prompt: (
|
|
@@ -397,78 +406,81 @@ class ModelRequest:
|
|
|
397
406
|
self.prompt.clear()
|
|
398
407
|
return response
|
|
399
408
|
|
|
409
|
+
async def get_result(self):
|
|
410
|
+
return self.get_response().result
|
|
411
|
+
|
|
400
412
|
async def async_get_meta(self):
|
|
401
413
|
return await self.get_response().async_get_meta()
|
|
402
414
|
|
|
403
415
|
async def async_get_text(self):
|
|
404
416
|
return await self.get_response().async_get_text()
|
|
405
417
|
|
|
406
|
-
async def
|
|
418
|
+
async def async_get_data(
|
|
407
419
|
self,
|
|
408
420
|
*,
|
|
409
|
-
|
|
421
|
+
type: Literal['original', 'parsed', 'all'] = "parsed",
|
|
410
422
|
):
|
|
411
|
-
return await self.get_response().
|
|
423
|
+
return await self.get_response().async_get_data(type=type)
|
|
412
424
|
|
|
413
|
-
async def
|
|
414
|
-
return await self.get_response().
|
|
425
|
+
async def async_get_data_object(self):
|
|
426
|
+
return await self.get_response().async_get_data_object()
|
|
415
427
|
|
|
416
428
|
@overload
|
|
417
429
|
def get_generator(
|
|
418
430
|
self,
|
|
419
|
-
|
|
431
|
+
type: Literal["instant", "streaming_parse"],
|
|
420
432
|
) -> Generator["StreamingData", None, None]: ...
|
|
421
433
|
|
|
422
434
|
@overload
|
|
423
435
|
def get_generator(
|
|
424
436
|
self,
|
|
425
|
-
|
|
437
|
+
type: Literal["all"],
|
|
426
438
|
) -> Generator[tuple[str, Any], None, None]: ...
|
|
427
439
|
|
|
428
440
|
@overload
|
|
429
441
|
def get_generator(
|
|
430
442
|
self,
|
|
431
|
-
|
|
443
|
+
type: Literal["delta", "typed_delta", "original"],
|
|
432
444
|
) -> Generator[str, None, None]: ...
|
|
433
445
|
|
|
434
446
|
@overload
|
|
435
447
|
def get_generator(
|
|
436
448
|
self,
|
|
437
|
-
|
|
449
|
+
type: Literal["all", "original", "delta", "typed_delta", "instant", "streaming_parse"] | None = "delta",
|
|
438
450
|
) -> Generator: ...
|
|
439
451
|
|
|
440
452
|
def get_generator(
|
|
441
453
|
self,
|
|
442
|
-
|
|
454
|
+
type: Literal["all", "original", "delta", "typed_delta", "instant", "streaming_parse"] | None = "delta",
|
|
443
455
|
) -> Generator:
|
|
444
|
-
return self.get_response().get_generator(
|
|
456
|
+
return self.get_response().get_generator(type=type)
|
|
445
457
|
|
|
446
458
|
@overload
|
|
447
459
|
def get_async_generator(
|
|
448
460
|
self,
|
|
449
|
-
|
|
461
|
+
type: Literal["instant", "streaming_parse"],
|
|
450
462
|
) -> AsyncGenerator["StreamingData", None]: ...
|
|
451
463
|
|
|
452
464
|
@overload
|
|
453
465
|
def get_async_generator(
|
|
454
466
|
self,
|
|
455
|
-
|
|
467
|
+
type: Literal["all"],
|
|
456
468
|
) -> AsyncGenerator[tuple[str, Any], None]: ...
|
|
457
469
|
|
|
458
470
|
@overload
|
|
459
471
|
def get_async_generator(
|
|
460
472
|
self,
|
|
461
|
-
|
|
473
|
+
type: Literal["delta", "typed_delta", "original"],
|
|
462
474
|
) -> AsyncGenerator[str, None]: ...
|
|
463
475
|
|
|
464
476
|
@overload
|
|
465
477
|
def get_async_generator(
|
|
466
478
|
self,
|
|
467
|
-
|
|
479
|
+
type: Literal["all", "original", "delta", "typed_delta", "instant", "streaming_parse"] | None = "delta",
|
|
468
480
|
) -> AsyncGenerator: ...
|
|
469
481
|
|
|
470
482
|
def get_async_generator(
|
|
471
483
|
self,
|
|
472
|
-
|
|
484
|
+
type: Literal["all", "original", "delta", "typed_delta", "instant", "streaming_parse"] | None = "delta",
|
|
473
485
|
) -> AsyncGenerator:
|
|
474
|
-
return self.get_response().get_async_generator(
|
|
486
|
+
return self.get_response().get_async_generator(type=type)
|
agently/types/data/prompt.py
CHANGED
|
@@ -118,6 +118,7 @@ PromptStandardSlot = Literal[
|
|
|
118
118
|
"tools",
|
|
119
119
|
"action_results",
|
|
120
120
|
"instruct",
|
|
121
|
+
"examples",
|
|
121
122
|
"input",
|
|
122
123
|
"attachment",
|
|
123
124
|
"output",
|
|
@@ -141,6 +142,7 @@ class PromptModel(BaseModel):
|
|
|
141
142
|
tools: list[ToolMeta] | None = None
|
|
142
143
|
action_results: Any = None
|
|
143
144
|
instruct: Any = None
|
|
145
|
+
examples: Any = None
|
|
144
146
|
input: Any = None
|
|
145
147
|
attachment: Annotated[list[ChatMessageContent], PlainValidator(validate_attachment)] = []
|
|
146
148
|
output: Any = None
|
agently/types/data/response.py
CHANGED
|
@@ -23,7 +23,9 @@ if TYPE_CHECKING:
|
|
|
23
23
|
from agently.utils import GeneratorConsumer
|
|
24
24
|
from agently.types.data.serializable import SerializableValue
|
|
25
25
|
|
|
26
|
-
AgentlyModelResponseEvent = Literal[
|
|
26
|
+
AgentlyModelResponseEvent = Literal[
|
|
27
|
+
"error", "original_delta", "delta", "tool_calls", "original_done", "done", "meta", "extra"
|
|
28
|
+
]
|
|
27
29
|
|
|
28
30
|
AgentlyModelResponseMessage: TypeAlias = tuple[AgentlyModelResponseEvent, Any]
|
|
29
31
|
AgentlyResponseGenerator: TypeAlias = AsyncGenerator[AgentlyModelResponseMessage, None]
|
|
@@ -53,21 +53,21 @@ class ResponseParser(AgentlyPlugin, Protocol):
|
|
|
53
53
|
|
|
54
54
|
async def async_get_meta(self) -> "SerializableData": ...
|
|
55
55
|
|
|
56
|
-
def
|
|
56
|
+
def get_data(
|
|
57
57
|
self,
|
|
58
58
|
*,
|
|
59
|
-
|
|
59
|
+
type: Literal["original", "parsed", "all"] = "parsed",
|
|
60
60
|
) -> Any: ...
|
|
61
61
|
|
|
62
|
-
async def
|
|
62
|
+
async def async_get_data(
|
|
63
63
|
self,
|
|
64
64
|
*,
|
|
65
|
-
|
|
65
|
+
type: Literal["original", "parsed", "all"] = "parsed",
|
|
66
66
|
) -> Any: ...
|
|
67
67
|
|
|
68
|
-
def
|
|
68
|
+
def get_data_object(self) -> "BaseModel | None": ...
|
|
69
69
|
|
|
70
|
-
async def
|
|
70
|
+
async def async_get_data_object(self) -> "BaseModel | None": ...
|
|
71
71
|
|
|
72
72
|
def get_text(self) -> str: ...
|
|
73
73
|
|
|
@@ -76,30 +76,30 @@ class ResponseParser(AgentlyPlugin, Protocol):
|
|
|
76
76
|
@overload
|
|
77
77
|
def get_async_generator(
|
|
78
78
|
self,
|
|
79
|
-
|
|
79
|
+
type: Literal["instant", "streaming_parse"],
|
|
80
80
|
) -> AsyncGenerator["StreamingData", None]: ...
|
|
81
81
|
|
|
82
82
|
@overload
|
|
83
83
|
def get_async_generator(
|
|
84
84
|
self,
|
|
85
|
-
|
|
85
|
+
type: Literal["all"],
|
|
86
86
|
) -> AsyncGenerator[tuple[str, Any], None]: ...
|
|
87
87
|
|
|
88
88
|
@overload
|
|
89
89
|
def get_async_generator(
|
|
90
90
|
self,
|
|
91
|
-
|
|
91
|
+
type: Literal["delta", "typed_delta", "original"],
|
|
92
92
|
) -> AsyncGenerator[str, None]: ...
|
|
93
93
|
|
|
94
94
|
@overload
|
|
95
95
|
def get_async_generator(
|
|
96
96
|
self,
|
|
97
|
-
|
|
97
|
+
type: Literal["all", "original", "delta", "typed_delta", "instant", "streaming_parse"] | None = "delta",
|
|
98
98
|
) -> AsyncGenerator: ...
|
|
99
99
|
|
|
100
100
|
def get_async_generator(
|
|
101
101
|
self,
|
|
102
|
-
|
|
102
|
+
type: Literal["all", "original", "delta", "typed_delta", "instant", "streaming_parse"] | None = "delta",
|
|
103
103
|
) -> AsyncGenerator:
|
|
104
104
|
"""
|
|
105
105
|
'instant' is Agently v3 compatible for 'streaming_parse'
|
|
@@ -109,30 +109,30 @@ class ResponseParser(AgentlyPlugin, Protocol):
|
|
|
109
109
|
@overload
|
|
110
110
|
def get_generator(
|
|
111
111
|
self,
|
|
112
|
-
|
|
112
|
+
type: Literal["instant", "streaming_parse"],
|
|
113
113
|
) -> Generator["StreamingData", None, None]: ...
|
|
114
114
|
|
|
115
115
|
@overload
|
|
116
116
|
def get_generator(
|
|
117
117
|
self,
|
|
118
|
-
|
|
118
|
+
type: Literal["all"],
|
|
119
119
|
) -> Generator[tuple[str, Any], None, None]: ...
|
|
120
120
|
|
|
121
121
|
@overload
|
|
122
122
|
def get_generator(
|
|
123
123
|
self,
|
|
124
|
-
|
|
124
|
+
type: Literal["delta", "typed_delta", "original"],
|
|
125
125
|
) -> Generator[str, None, None]: ...
|
|
126
126
|
|
|
127
127
|
@overload
|
|
128
128
|
def get_generator(
|
|
129
129
|
self,
|
|
130
|
-
|
|
130
|
+
type: Literal["all", "original", "delta", "typed_delta", "instant", "streaming_parse"] | None = "delta",
|
|
131
131
|
) -> Generator: ...
|
|
132
132
|
|
|
133
133
|
def get_generator(
|
|
134
134
|
self,
|
|
135
|
-
|
|
135
|
+
type: Literal["all", "original", "delta", "typed_delta", "instant", "streaming_parse"] | None = "delta",
|
|
136
136
|
) -> Generator:
|
|
137
137
|
"""
|
|
138
138
|
'instant' is Agently v3 compatible for 'streaming_parse'
|
agently/utils/FunctionShifter.py
CHANGED
|
@@ -12,12 +12,13 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
import queue
|
|
15
16
|
import asyncio
|
|
16
17
|
import threading
|
|
17
18
|
from functools import wraps
|
|
18
19
|
|
|
19
20
|
import inspect
|
|
20
|
-
from typing import Any, Callable, Coroutine, TypeVar, ParamSpec
|
|
21
|
+
from typing import Any, Callable, Coroutine, TypeVar, ParamSpec, Generator, AsyncGenerator
|
|
21
22
|
from asyncio import Future
|
|
22
23
|
|
|
23
24
|
T = TypeVar("T")
|
|
@@ -107,16 +108,65 @@ class FunctionShifter:
|
|
|
107
108
|
return wrapper
|
|
108
109
|
|
|
109
110
|
@staticmethod
|
|
110
|
-
def syncify_async_generator(async_gen):
|
|
111
|
-
loop = asyncio.new_event_loop()
|
|
111
|
+
def syncify_async_generator(async_gen: AsyncGenerator[R, Any]) -> Generator[R, Any, Any]:
|
|
112
112
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
113
|
+
q: "queue.Queue" = queue.Queue()
|
|
114
|
+
SENTINEL = object()
|
|
115
|
+
|
|
116
|
+
async def _consume():
|
|
117
|
+
try:
|
|
118
|
+
async for item in async_gen:
|
|
119
|
+
q.put(("item", item))
|
|
120
|
+
except Exception as e:
|
|
121
|
+
q.put(("error", e))
|
|
122
|
+
finally:
|
|
123
|
+
q.put(("end", SENTINEL))
|
|
124
|
+
|
|
125
|
+
def _runner():
|
|
126
|
+
loop = asyncio.new_event_loop()
|
|
127
|
+
try:
|
|
128
|
+
asyncio.set_event_loop(loop)
|
|
129
|
+
loop.run_until_complete(_consume())
|
|
130
|
+
finally:
|
|
131
|
+
loop.close()
|
|
132
|
+
asyncio.set_event_loop(None)
|
|
133
|
+
|
|
134
|
+
thread = threading.Thread(target=_runner, daemon=True)
|
|
135
|
+
thread.start()
|
|
118
136
|
|
|
119
137
|
try:
|
|
120
|
-
|
|
138
|
+
while True:
|
|
139
|
+
kind, payload = q.get()
|
|
140
|
+
if kind == "item":
|
|
141
|
+
yield payload
|
|
142
|
+
elif kind == "error":
|
|
143
|
+
raise payload
|
|
144
|
+
elif kind == "end":
|
|
145
|
+
break
|
|
121
146
|
finally:
|
|
122
|
-
|
|
147
|
+
thread.join()
|
|
148
|
+
|
|
149
|
+
@staticmethod
|
|
150
|
+
def auto_options_func(func: Callable[..., R]) -> Callable[..., R]:
|
|
151
|
+
signature = inspect.signature(func)
|
|
152
|
+
params = signature.parameters
|
|
153
|
+
accepts_kwargs = any(p.kind == inspect.Parameter.VAR_KEYWORD for p in params.values())
|
|
154
|
+
|
|
155
|
+
@wraps(func)
|
|
156
|
+
def _wrapper(*args, **kwargs):
|
|
157
|
+
if not accepts_kwargs:
|
|
158
|
+
kwargs = {
|
|
159
|
+
name: value
|
|
160
|
+
for name, value in kwargs.items()
|
|
161
|
+
if name in params
|
|
162
|
+
and params[name].kind
|
|
163
|
+
in (
|
|
164
|
+
inspect.Parameter.POSITIONAL_OR_KEYWORD,
|
|
165
|
+
inspect.Parameter.KEYWORD_ONLY,
|
|
166
|
+
)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
result = func(*args, **kwargs)
|
|
170
|
+
return result
|
|
171
|
+
|
|
172
|
+
return _wrapper
|
agently/utils/Storage.py
CHANGED
|
@@ -25,9 +25,14 @@ from typing import (
|
|
|
25
25
|
)
|
|
26
26
|
from contextlib import asynccontextmanager
|
|
27
27
|
|
|
28
|
-
from
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
from agently.utils import LazyImport
|
|
29
|
+
|
|
30
|
+
LazyImport.import_package("sqlmodel")
|
|
31
|
+
LazyImport.import_package("sqlalchemy")
|
|
32
|
+
|
|
33
|
+
from sqlmodel import SQLModel, select, inspect, create_engine, Session # type: ignore
|
|
34
|
+
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker # type: ignore
|
|
35
|
+
from sqlalchemy.sql import ColumnElement # type: ignore
|
|
31
36
|
|
|
32
37
|
from .RuntimeData import RuntimeData
|
|
33
38
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agently
|
|
3
|
-
Version: 4.0.
|
|
3
|
+
Version: 4.0.6.1
|
|
4
4
|
Summary:
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
License-File: LICENSE
|
|
@@ -19,9 +19,9 @@ Requires-Dist: greenlet (>=3.2.3,<4.0.0)
|
|
|
19
19
|
Requires-Dist: httpx (>=0.28.1,<0.29.0)
|
|
20
20
|
Requires-Dist: httpx-sse (>=0.4.1,<0.5.0)
|
|
21
21
|
Requires-Dist: json5 (>=0.12.0,<0.13.0)
|
|
22
|
+
Requires-Dist: packaging (>=25.0,<26.0)
|
|
22
23
|
Requires-Dist: pydantic (>=2.11.7,<3.0.0)
|
|
23
24
|
Requires-Dist: pyyaml (>=6.0.2,<7.0.0)
|
|
24
|
-
Requires-Dist: sqlmodel (>=0.0.24,<0.0.25)
|
|
25
25
|
Requires-Dist: stamina (>=25.1.0,<26.0.0)
|
|
26
26
|
Requires-Dist: toml (>=0.10.2,<0.11.0)
|
|
27
27
|
Description-Content-Type: text/markdown
|
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
agently/__init__.py,sha256=Gf0LL7Czqeuf6hfvHfEGlACLg0d0osQupyMATB0EBlc,884
|
|
2
2
|
agently/_default_init.py,sha256=AhYwzZYOxqDeIoVb8cvPjJ2BjE5V7wxeuH7R-MNZWyg,2057
|
|
3
|
-
agently/_default_settings.yaml,sha256=
|
|
3
|
+
agently/_default_settings.yaml,sha256=6woqJ2tjg_jl6kwSOwmTMETfVraHidort2smf0Is_qQ,1357
|
|
4
4
|
agently/base.py,sha256=PY-HgIQesv3_oBsU25Fwe96C35C4GgpaFdxLBUwh-AA,4692
|
|
5
5
|
agently/builtins/agent_extensions/AutoFuncExtension.py,sha256=TmwMazwPzb5WXfDqfedY5yZOOMTFIHqaB9Bte29adUc,2433
|
|
6
6
|
agently/builtins/agent_extensions/ChatSessionExtension.py,sha256=Y6mvnsfAY0rykKtfp-tApwJy5O4SS-YEt2-jaWr83uc,12034
|
|
7
7
|
agently/builtins/agent_extensions/ConfigurePromptExtension.py,sha256=A5rYGTa0oSh1N0CdtHQSypFJqcQJm5v5CcCWRnI7iP0,10190
|
|
8
|
-
agently/builtins/agent_extensions/KeyWaiterExtension.py,sha256=
|
|
9
|
-
agently/builtins/agent_extensions/ToolExtension.py,sha256=
|
|
8
|
+
agently/builtins/agent_extensions/KeyWaiterExtension.py,sha256=Rf8dB8Yt3_9IJifpiE-Rn6lLIXqZjaNp94lnX6Betgw,5555
|
|
9
|
+
agently/builtins/agent_extensions/ToolExtension.py,sha256=S3jjumHiauEQ-m46Zkh-1I9ih02kKoj8sBEU82woz1E,6886
|
|
10
10
|
agently/builtins/agent_extensions/__init__.py,sha256=IxWRQogF8PCVNXeY7D4qhGukEx3JFvfLlUW2x0FbyfA,852
|
|
11
11
|
agently/builtins/hookers/ConsoleHooker.py,sha256=aJdDj_nG8CiwyelA505zvtpzBSwD52nFIkBRDJGgq3Y,8099
|
|
12
12
|
agently/builtins/hookers/PureLoggerHooker.py,sha256=fzN0OfhQzgns4KeCNH-qcdm-BdQT0W2kqEmt3Zp2pYI,1906
|
|
13
13
|
agently/builtins/hookers/SystemMessageHooker.py,sha256=nU5rOzcuXKdaTXWix3jhZ-4QoD4cMQJZo02wNTpZpjI,5396
|
|
14
|
-
agently/builtins/plugins/ModelRequester/OpenAICompatible.py,sha256=
|
|
15
|
-
agently/builtins/plugins/PromptGenerator/AgentlyPromptGenerator.py,sha256=
|
|
16
|
-
agently/builtins/plugins/ResponseParser/AgentlyResponseParser.py,sha256=
|
|
14
|
+
agently/builtins/plugins/ModelRequester/OpenAICompatible.py,sha256=dfVDoqTZAZrjBZUusH72-uUGh2Co_p4CkOrMDyeaTaQ,25059
|
|
15
|
+
agently/builtins/plugins/PromptGenerator/AgentlyPromptGenerator.py,sha256=hUj3bkWLZvLmYwJoFpEfGjbF0VL-gKiHHoKoHFJgzvs,28906
|
|
16
|
+
agently/builtins/plugins/ResponseParser/AgentlyResponseParser.py,sha256=FEhfsiHB4Bx7HfghnObklLj08j8IVwGh0WEVD6U-G3U,17445
|
|
17
17
|
agently/builtins/plugins/ToolManager/AgentlyToolManager.py,sha256=23fyWAPw9wLIH2bkrbeKzThzA0z4Lvy8b9Qvp8SrGJE,8381
|
|
18
18
|
agently/builtins/plugins/__init__.py,sha256=wj4_U9TTekc2CmjppbXKUREDFRXFX1y0ySOW-CxQuok,801
|
|
19
19
|
agently/builtins/tools/Browse.py,sha256=gIePs-gtsqOI_ZTReGqEcoKvhs4FkBzTxow--QS5_ek,3469
|
|
20
|
-
agently/builtins/tools/Search.py,sha256=
|
|
20
|
+
agently/builtins/tools/Search.py,sha256=tUynNiW_ZMAGaB2ua3HRcY_trIbLEoASFE-p2QMQ0Zg,7362
|
|
21
21
|
agently/builtins/tools/__init__.py,sha256=pFOWgH2C3xRvgQo3UVdkj4yHjF9nNtmoVHmOZfoGsyU,647
|
|
22
|
-
agently/core/Agent.py,sha256=
|
|
22
|
+
agently/core/Agent.py,sha256=HbUqlCWFgtziavN8r-2RFQyrbHMMxKA6y-io-0CY8TA,9022
|
|
23
23
|
agently/core/EventCenter.py,sha256=sknU5w9MpGDQgMOF9c5k4PfM4SNT5X_LrpYte2HaFNM,10861
|
|
24
24
|
agently/core/ExtensionHandlers.py,sha256=88iSAW50bgMshB56cTgKg30eOjZQyXiJY1en4w7afWY,2076
|
|
25
|
-
agently/core/ModelRequest.py,sha256=
|
|
25
|
+
agently/core/ModelRequest.py,sha256=LetLuKwWXtmC7JWd2UinW2e-egJhxUMZ__L0SOvu3c4,17399
|
|
26
26
|
agently/core/PluginManager.py,sha256=oUnXbe1ilQTOWwnENxtGtV6wG-yZriCxniqfuxuTFO0,4354
|
|
27
27
|
agently/core/Prompt.py,sha256=8SlqytnAIM_FIWbY2Jx-T7yOs_jqmkz9cux8-2iOCjA,8023
|
|
28
28
|
agently/core/Tool.py,sha256=PNYf_BwVefr8IOqf5asLaVq2fU7hQaFJwJVj3S4fq84,1871
|
|
@@ -41,15 +41,15 @@ agently/integrations/chromadb.py,sha256=2jkOPyKRR4hT7lwtMkaZq27wGL4wGmsRb2rpn7_2
|
|
|
41
41
|
agently/types/__init__.py,sha256=xb8GMY-ULncO_PY9rfRUsyi12wAQQJx8gAAnoM30uZA,592
|
|
42
42
|
agently/types/data/__init__.py,sha256=qladqSEqcAUW_XzdTDl4cvaraq_DpANy3aZbIPxoygk,1627
|
|
43
43
|
agently/types/data/event.py,sha256=LFQW7MN_QGOis3XV-8K6jNXWsLvT7tYxo4BZbUBCpfI,1790
|
|
44
|
-
agently/types/data/prompt.py,sha256=
|
|
44
|
+
agently/types/data/prompt.py,sha256=DiszVM_3OHe66waf-99mBH7bzRr0cpbCHSpDI-2EjPs,5163
|
|
45
45
|
agently/types/data/request.py,sha256=Do-9g5QxZRMYjaoHCZYwHbj28r-t4noAAtOebw764P4,1924
|
|
46
|
-
agently/types/data/response.py,sha256=
|
|
46
|
+
agently/types/data/response.py,sha256=vjKIILaVyd5TVz5nvmytVRJPZg-RP0sRydhg_AzU6y0,3700
|
|
47
47
|
agently/types/data/serializable.py,sha256=v2KlyKNOKp4L6J_Ueupb-gCyrnngvBskFUwNPSJQgnA,844
|
|
48
48
|
agently/types/data/tool.py,sha256=wpNSyv_sCS8MWYcd6rewLDCleb3umpF7mf2hwtrm4_o,1518
|
|
49
49
|
agently/types/plugins/EventHooker.py,sha256=kb80-baVc3fVlrddW5syv9uSD8a2Mcw8Fd3I2HQhY_Y,1030
|
|
50
50
|
agently/types/plugins/ModelRequester.py,sha256=urG1zFX0b4U6ZKSO50IbW5IHK3ydmRgUom7O7Niqk8s,3875
|
|
51
51
|
agently/types/plugins/PromptGenerator.py,sha256=45jmVzAkyl1Yj2M8RVfQM_zFAJZP4zrPuQkHbWIQSRQ,4531
|
|
52
|
-
agently/types/plugins/ResponseParser.py,sha256=
|
|
52
|
+
agently/types/plugins/ResponseParser.py,sha256=_IRbQhT-G1ZNg2zkJgCYNF5qRaIzrDfbxLC7kO-tdK4,3984
|
|
53
53
|
agently/types/plugins/ToolManager.py,sha256=q1Y3G_tzh1AU3s13H-zTDZIkR4W1mjh9E6AKudFOvyg,2421
|
|
54
54
|
agently/types/plugins/__init__.py,sha256=gz_EpgBQGndIQHY5vJB2YRzAN5yIb3FZZG7pC8lB1lM,848
|
|
55
55
|
agently/types/plugins/base.py,sha256=AoNLwsH5IZBQt7_NZfxMWMhAk6PJSOFHR0IYOXp1imI,1167
|
|
@@ -58,7 +58,7 @@ agently/types/trigger_flow/trigger_flow.py,sha256=uDUZiila_4Rr41zUlzR4QqaRaraC43
|
|
|
58
58
|
agently/utils/DataFormatter.py,sha256=Ni1aMmnc_6lDowTCSd3EVT-5i9DjbsWFex3EZS_14Vk,9044
|
|
59
59
|
agently/utils/DataLocator.py,sha256=ss8OLet9HN0U1PZb-OCHS6KL54kv7vFZph6G0-GBidk,6015
|
|
60
60
|
agently/utils/DataPathBuilder.py,sha256=sEzE1i2EWn7NMkCCXDT50gR6_qMzcZ0y0YGkYbXdB3s,10007
|
|
61
|
-
agently/utils/FunctionShifter.py,sha256=
|
|
61
|
+
agently/utils/FunctionShifter.py,sha256=quwugTmf-vzHzRR_2wdv14AxLpr0lwxdUtVoX7Jeq48,5839
|
|
62
62
|
agently/utils/GeneratorConsumer.py,sha256=EXpz2XGnv6rPdz8bPetJu3LpWIVhMvIi8GLG1Bpe7Ys,7459
|
|
63
63
|
agently/utils/LazyImport.py,sha256=PfXc2iILXb7WVj6UD45_3qInow6z0cvhFlDqxTK-HfY,9120
|
|
64
64
|
agently/utils/Logger.py,sha256=reIj6a7mNtLYDx3brLKEf0I8LbNkhXmL8Yc-DXnnsCU,2967
|
|
@@ -66,11 +66,11 @@ agently/utils/Messenger.py,sha256=dLasJvDt1HxJttt6X9dutwGPvyAtL7yp6BZ3TDxuFDI,72
|
|
|
66
66
|
agently/utils/RuntimeData.py,sha256=SewZ8D1fljuDwfVZTAqZ0XTNEcU2cuAr7QlVqk0vzrE,21925
|
|
67
67
|
agently/utils/SerializableRuntimeData.py,sha256=bVVwin50VnOs30W881ClFepSXAK8GCOUZnVd-SiolRw,3314
|
|
68
68
|
agently/utils/Settings.py,sha256=_s300H2doCMKcvMAmFwW3cLQqmd0N8BVmb226tAfVec,5294
|
|
69
|
-
agently/utils/Storage.py,sha256=
|
|
69
|
+
agently/utils/Storage.py,sha256=pQtD_nA3rsp18c9avYDR6eKmHeghYwaNrW8vqerOXpM,9401
|
|
70
70
|
agently/utils/StreamingJSONCompleter.py,sha256=aZ9zuGUTQlP-QKbXHUZCf6EtVuG49MKn8xdhw0VhDEA,4292
|
|
71
71
|
agently/utils/StreamingJSONParser.py,sha256=sPPJOtj5OYvsrukRErcoxRl4yuV1zDuf7pQ_pvw_Zow,21116
|
|
72
72
|
agently/utils/__init__.py,sha256=NXiBzE-pOYxukqCVBmCmGUwlVuqe2w5inwxzg3IUkaw,1277
|
|
73
|
-
agently-4.0.
|
|
74
|
-
agently-4.0.
|
|
75
|
-
agently-4.0.
|
|
76
|
-
agently-4.0.
|
|
73
|
+
agently-4.0.6.1.dist-info/METADATA,sha256=1l8uNJ2T8bujH19yBJxsFzdC4cIAbVThUAlWV9dy5Qo,7156
|
|
74
|
+
agently-4.0.6.1.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
75
|
+
agently-4.0.6.1.dist-info/licenses/LICENSE,sha256=Y5ZgAdYgMFigPT8dhN18dTLRtBshOSfWhTDRO1t0Cq4,11360
|
|
76
|
+
agently-4.0.6.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|