grasp_agents 0.3.2__py3-none-any.whl → 0.3.5__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.
- grasp_agents/llm.py +26 -23
- grasp_agents/llm_agent.py +55 -57
- grasp_agents/llm_policy_executor.py +12 -10
- grasp_agents/printer.py +1 -1
- grasp_agents/prompt_builder.py +13 -18
- grasp_agents/run_context.py +2 -2
- grasp_agents/utils.py +13 -7
- {grasp_agents-0.3.2.dist-info → grasp_agents-0.3.5.dist-info}/METADATA +1 -1
- {grasp_agents-0.3.2.dist-info → grasp_agents-0.3.5.dist-info}/RECORD +11 -11
- {grasp_agents-0.3.2.dist-info → grasp_agents-0.3.5.dist-info}/WHEEL +0 -0
- {grasp_agents-0.3.2.dist-info → grasp_agents-0.3.5.dist-info}/licenses/LICENSE.md +0 -0
grasp_agents/llm.py
CHANGED
@@ -39,7 +39,7 @@ class LLM(ABC, Generic[SettingsT_co, ConvertT_co]):
|
|
39
39
|
model_id: str | None = None,
|
40
40
|
llm_settings: SettingsT_co | None = None,
|
41
41
|
tools: list[BaseTool[BaseModel, Any, Any]] | None = None,
|
42
|
-
response_format:
|
42
|
+
response_format: Any | Mapping[str, Any] | None = None,
|
43
43
|
**kwargs: Any,
|
44
44
|
) -> None:
|
45
45
|
super().__init__()
|
@@ -51,15 +51,19 @@ class LLM(ABC, Generic[SettingsT_co, ConvertT_co]):
|
|
51
51
|
self._llm_settings: SettingsT_co = llm_settings or cast("SettingsT_co", {})
|
52
52
|
|
53
53
|
self._response_format = response_format
|
54
|
-
self._response_format_adapter:
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
54
|
+
self._response_format_adapter: (
|
55
|
+
TypeAdapter[Any] | Mapping[str, TypeAdapter[Any]]
|
56
|
+
) = self._get_response_format_adapter(response_format=response_format)
|
57
|
+
|
58
|
+
@staticmethod
|
59
|
+
def _get_response_format_adapter(
|
60
|
+
response_format: Any | Mapping[str, Any] | None = None,
|
61
|
+
) -> TypeAdapter[Any] | Mapping[str, TypeAdapter[Any]]:
|
62
|
+
if response_format is None:
|
63
|
+
return TypeAdapter(Any)
|
64
|
+
if isinstance(response_format, Mapping):
|
65
|
+
return {k: TypeAdapter(v) for k, v in response_format.items()} # type: ignore[return-value]
|
66
|
+
return TypeAdapter(response_format)
|
63
67
|
|
64
68
|
@property
|
65
69
|
def model_id(self) -> str:
|
@@ -74,23 +78,24 @@ class LLM(ABC, Generic[SettingsT_co, ConvertT_co]):
|
|
74
78
|
return self._llm_settings
|
75
79
|
|
76
80
|
@property
|
77
|
-
def
|
78
|
-
return self.
|
81
|
+
def response_format(self) -> Any | Mapping[str, Any] | None:
|
82
|
+
return self._response_format
|
83
|
+
|
84
|
+
@response_format.setter
|
85
|
+
def response_format(self, response_format: Any | Mapping[str, Any] | None) -> None:
|
86
|
+
self._response_format = response_format
|
87
|
+
self._response_format_adapter = self._get_response_format_adapter(
|
88
|
+
response_format
|
89
|
+
)
|
79
90
|
|
80
91
|
@property
|
81
|
-
def
|
82
|
-
return self.
|
92
|
+
def tools(self) -> dict[str, BaseTool[BaseModel, Any, Any]] | None:
|
93
|
+
return self._tools
|
83
94
|
|
84
95
|
@tools.setter
|
85
96
|
def tools(self, tools: list[BaseTool[BaseModel, Any, Any]] | None) -> None:
|
86
97
|
self._tools = {t.name: t for t in tools} if tools else None
|
87
98
|
|
88
|
-
@response_format.setter
|
89
|
-
def response_format(
|
90
|
-
self, response_format: type | Mapping[str, type] | None
|
91
|
-
) -> None:
|
92
|
-
self._response_format = response_format
|
93
|
-
|
94
99
|
def __repr__(self) -> str:
|
95
100
|
return (
|
96
101
|
f"{type(self).__name__}(model_id={self.model_id}; "
|
@@ -101,9 +106,7 @@ class LLM(ABC, Generic[SettingsT_co, ConvertT_co]):
|
|
101
106
|
for message in completion.messages:
|
102
107
|
if not message.tool_calls:
|
103
108
|
validate_obj_from_json_or_py_string(
|
104
|
-
message.content or "",
|
105
|
-
adapter=self._response_format_adapter,
|
106
|
-
from_substring=True,
|
109
|
+
message.content or "", adapter=self._response_format_adapter
|
107
110
|
)
|
108
111
|
|
109
112
|
def _validate_tool_calls(self, completion: Completion) -> None:
|
grasp_agents/llm_agent.py
CHANGED
@@ -63,9 +63,9 @@ class LLMAgent(
|
|
63
63
|
sys_prompt: LLMPrompt | None = None,
|
64
64
|
sys_prompt_path: str | Path | None = None,
|
65
65
|
# System args (static args provided via RunContext)
|
66
|
-
sys_args_schema: type[LLMPromptArgs] =
|
66
|
+
sys_args_schema: type[LLMPromptArgs] | None = None,
|
67
67
|
# User args (static args provided via RunContext)
|
68
|
-
usr_args_schema: type[LLMPromptArgs] =
|
68
|
+
usr_args_schema: type[LLMPromptArgs] | None = None,
|
69
69
|
# Agent loop settings
|
70
70
|
max_turns: int = 100,
|
71
71
|
react_mode: bool = False,
|
@@ -82,14 +82,13 @@ class LLMAgent(
|
|
82
82
|
|
83
83
|
self._memory: LLMAgentMemory = LLMAgentMemory()
|
84
84
|
self._reset_memory_on_run = reset_memory_on_run
|
85
|
-
self._set_memory_impl: SetMemoryHandler | None = None
|
86
85
|
|
87
86
|
# LLM policy executor
|
88
87
|
|
89
|
-
self.
|
88
|
+
self._used_default_llm_response_format: bool = False
|
90
89
|
if llm.response_format is None and tools is None:
|
91
90
|
llm.response_format = self.out_type
|
92
|
-
self.
|
91
|
+
self._used_default_llm_response_format = True
|
93
92
|
|
94
93
|
self._policy_executor: LLMPolicyExecutor[OutT_co, CtxT] = LLMPolicyExecutor[
|
95
94
|
self.out_type, CtxT
|
@@ -118,6 +117,10 @@ class LLMAgent(
|
|
118
117
|
|
119
118
|
self.no_tqdm = getattr(llm, "no_tqdm", False)
|
120
119
|
|
120
|
+
self._set_memory_impl: SetMemoryHandler | None = None
|
121
|
+
self._parse_output_impl: (
|
122
|
+
ParseOutputHandler[InT_contra, OutT_co, CtxT] | None
|
123
|
+
) = None
|
121
124
|
self._register_overridden_handlers()
|
122
125
|
|
123
126
|
@property
|
@@ -148,32 +151,6 @@ class LLMAgent(
|
|
148
151
|
def in_prompt(self) -> LLMPrompt | None:
|
149
152
|
return self._prompt_builder.in_prompt_template
|
150
153
|
|
151
|
-
def _parse_output(
|
152
|
-
self,
|
153
|
-
conversation: Messages,
|
154
|
-
*,
|
155
|
-
in_args: InT_contra | None = None,
|
156
|
-
batch_idx: int = 0,
|
157
|
-
ctx: RunContext[CtxT] | None = None,
|
158
|
-
) -> OutT_co:
|
159
|
-
if self._parse_output_impl:
|
160
|
-
if self._using_default_llm_response_format:
|
161
|
-
# When using custom output parsing, the required LLM response format
|
162
|
-
# can differ from the final agent output type ->
|
163
|
-
# set it back to None unless it was specified explicitly at init.
|
164
|
-
self._policy_executor.llm.response_format = None
|
165
|
-
# self._using_default_llm_response_format = False
|
166
|
-
|
167
|
-
return self._parse_output_impl(
|
168
|
-
conversation=conversation, in_args=in_args, batch_idx=batch_idx, ctx=ctx
|
169
|
-
)
|
170
|
-
|
171
|
-
return validate_obj_from_json_or_py_string(
|
172
|
-
str(conversation[-1].content or ""),
|
173
|
-
adapter=self._out_type_adapter,
|
174
|
-
from_substring=True,
|
175
|
-
)
|
176
|
-
|
177
154
|
def _memorize_inputs(
|
178
155
|
self,
|
179
156
|
chat_inputs: LLMPrompt | Sequence[str | ImageData] | None = None,
|
@@ -192,7 +169,7 @@ class LLMAgent(
|
|
192
169
|
|
193
170
|
# 1. Make system prompt (can be None)
|
194
171
|
|
195
|
-
formatted_sys_prompt = self._prompt_builder.
|
172
|
+
formatted_sys_prompt = self._prompt_builder.make_system_prompt(
|
196
173
|
sys_args=sys_args, ctx=ctx
|
197
174
|
)
|
198
175
|
|
@@ -251,6 +228,25 @@ class LLMAgent(
|
|
251
228
|
|
252
229
|
return outputs
|
253
230
|
|
231
|
+
def _parse_output(
|
232
|
+
self,
|
233
|
+
conversation: Messages,
|
234
|
+
*,
|
235
|
+
in_args: InT_contra | None = None,
|
236
|
+
batch_idx: int = 0,
|
237
|
+
ctx: RunContext[CtxT] | None = None,
|
238
|
+
) -> OutT_co:
|
239
|
+
if self._parse_output_impl:
|
240
|
+
return self._parse_output_impl(
|
241
|
+
conversation=conversation, in_args=in_args, batch_idx=batch_idx, ctx=ctx
|
242
|
+
)
|
243
|
+
|
244
|
+
return validate_obj_from_json_or_py_string(
|
245
|
+
str(conversation[-1].content or ""),
|
246
|
+
adapter=self._out_type_adapter,
|
247
|
+
from_substring=True,
|
248
|
+
)
|
249
|
+
|
254
250
|
async def _process(
|
255
251
|
self,
|
256
252
|
chat_inputs: LLMPrompt | Sequence[str | ImageData] | None = None,
|
@@ -313,23 +309,25 @@ class LLMAgent(
|
|
313
309
|
|
314
310
|
# -- Decorators for custom implementations --
|
315
311
|
|
316
|
-
def
|
312
|
+
def make_system_prompt(
|
317
313
|
self, func: MakeSystemPromptHandler[CtxT]
|
318
314
|
) -> MakeSystemPromptHandler[CtxT]:
|
319
|
-
self._prompt_builder.
|
315
|
+
self._prompt_builder.make_system_prompt_impl = func
|
320
316
|
|
321
317
|
return func
|
322
318
|
|
323
|
-
def
|
319
|
+
def make_input_content(
|
324
320
|
self, func: MakeInputContentHandler[InT_contra, CtxT]
|
325
321
|
) -> MakeInputContentHandler[InT_contra, CtxT]:
|
326
|
-
self._prompt_builder.
|
322
|
+
self._prompt_builder.make_input_content_impl = func
|
327
323
|
|
328
324
|
return func
|
329
325
|
|
330
326
|
def parse_output(
|
331
327
|
self, func: ParseOutputHandler[InT_contra, OutT_co, CtxT]
|
332
328
|
) -> ParseOutputHandler[InT_contra, OutT_co, CtxT]:
|
329
|
+
if self._used_default_llm_response_format:
|
330
|
+
self._policy_executor.llm.response_format = None
|
333
331
|
self._parse_output_impl = func
|
334
332
|
|
335
333
|
return func
|
@@ -359,30 +357,30 @@ class LLMAgent(
|
|
359
357
|
cur_cls = type(self)
|
360
358
|
base_cls = LLMAgent[Any, Any, Any]
|
361
359
|
|
362
|
-
if cur_cls.
|
363
|
-
self._prompt_builder.
|
360
|
+
if cur_cls._make_system_prompt is not base_cls._make_system_prompt: # noqa: SLF001
|
361
|
+
self._prompt_builder.make_system_prompt_impl = self._make_system_prompt
|
364
362
|
|
365
|
-
if cur_cls.
|
366
|
-
self._prompt_builder.
|
363
|
+
if cur_cls._make_input_content is not base_cls._make_input_content: # noqa: SLF001
|
364
|
+
self._prompt_builder.make_input_content_impl = self._make_input_content
|
367
365
|
|
368
|
-
if cur_cls.
|
369
|
-
self._set_memory_impl = self.
|
366
|
+
if cur_cls._set_memory is not base_cls._set_memory: # noqa: SLF001
|
367
|
+
self._set_memory_impl = self._set_memory
|
370
368
|
|
371
|
-
if cur_cls.
|
372
|
-
self._policy_executor.manage_memory_impl = self.
|
369
|
+
if cur_cls._manage_memory is not base_cls._manage_memory: # noqa: SLF001
|
370
|
+
self._policy_executor.manage_memory_impl = self._manage_memory
|
373
371
|
|
374
372
|
if (
|
375
|
-
cur_cls.
|
373
|
+
cur_cls._exit_tool_call_loop is not base_cls._exit_tool_call_loop # noqa: SLF001
|
376
374
|
):
|
377
|
-
self._policy_executor.exit_tool_call_loop_impl =
|
378
|
-
self._exit_tool_call_loop_fn
|
379
|
-
)
|
375
|
+
self._policy_executor.exit_tool_call_loop_impl = self._exit_tool_call_loop
|
380
376
|
|
381
|
-
|
382
|
-
|
383
|
-
|
377
|
+
if (
|
378
|
+
cur_cls._parse_output is not base_cls._parse_output # noqa: SLF001
|
379
|
+
and self._used_default_llm_response_format
|
380
|
+
):
|
381
|
+
self._policy_executor.llm.response_format = None
|
384
382
|
|
385
|
-
def
|
383
|
+
def _make_system_prompt(
|
386
384
|
self, sys_args: LLMPromptArgs | None, *, ctx: RunContext[CtxT] | None = None
|
387
385
|
) -> str:
|
388
386
|
raise NotImplementedError(
|
@@ -390,7 +388,7 @@ class LLMAgent(
|
|
390
388
|
"if it's intended to be used as the system arguments formatter."
|
391
389
|
)
|
392
390
|
|
393
|
-
def
|
391
|
+
def _make_input_content(
|
394
392
|
self,
|
395
393
|
*,
|
396
394
|
in_args: InT_contra | None = None,
|
@@ -402,10 +400,10 @@ class LLMAgent(
|
|
402
400
|
"LLMAgent._format_in_args must be overridden by a subclass"
|
403
401
|
)
|
404
402
|
|
405
|
-
def
|
403
|
+
def _set_memory(
|
406
404
|
self,
|
407
405
|
prev_memory: LLMAgentMemory,
|
408
|
-
in_args:
|
406
|
+
in_args: Sequence[InT_contra] | None = None,
|
409
407
|
sys_prompt: LLMPrompt | None = None,
|
410
408
|
ctx: RunContext[Any] | None = None,
|
411
409
|
) -> LLMAgentMemory:
|
@@ -413,7 +411,7 @@ class LLMAgent(
|
|
413
411
|
"LLMAgent._set_memory must be overridden by a subclass"
|
414
412
|
)
|
415
413
|
|
416
|
-
def
|
414
|
+
def _exit_tool_call_loop(
|
417
415
|
self,
|
418
416
|
conversation: Messages,
|
419
417
|
*,
|
@@ -424,7 +422,7 @@ class LLMAgent(
|
|
424
422
|
"LLMAgent._exit_tool_call_loop must be overridden by a subclass"
|
425
423
|
)
|
426
424
|
|
427
|
-
def
|
425
|
+
def _manage_memory(
|
428
426
|
self,
|
429
427
|
memory: LLMAgentMemory,
|
430
428
|
*,
|
@@ -28,6 +28,9 @@ from .typing.tool import BaseTool, NamedToolChoice, ToolCall, ToolChoice
|
|
28
28
|
logger = getLogger(__name__)
|
29
29
|
|
30
30
|
|
31
|
+
FINAL_ANSWER_TOOL_NAME = "final_answer"
|
32
|
+
|
33
|
+
|
31
34
|
_FinalAnswerT = TypeVar("_FinalAnswerT")
|
32
35
|
|
33
36
|
|
@@ -102,7 +105,7 @@ class LLMPolicyExecutor(AutoInstanceAttributesMixin, Generic[_FinalAnswerT, CtxT
|
|
102
105
|
def max_turns(self) -> int:
|
103
106
|
return self._max_turns
|
104
107
|
|
105
|
-
def
|
108
|
+
def _exit_tool_call_loop(
|
106
109
|
self,
|
107
110
|
conversation: Messages,
|
108
111
|
*,
|
@@ -119,7 +122,7 @@ class LLMPolicyExecutor(AutoInstanceAttributesMixin, Generic[_FinalAnswerT, CtxT
|
|
119
122
|
|
120
123
|
return not bool(conversation[-1].tool_calls)
|
121
124
|
|
122
|
-
def
|
125
|
+
def _manage_memory(
|
123
126
|
self,
|
124
127
|
memory: LLMAgentMemory,
|
125
128
|
*,
|
@@ -318,7 +321,7 @@ class LLMPolicyExecutor(AutoInstanceAttributesMixin, Generic[_FinalAnswerT, CtxT
|
|
318
321
|
|
319
322
|
# When final_answer_tool_name is None, we use exit_tool_call_loop_impl
|
320
323
|
# to determine whether to exit the loop.
|
321
|
-
if self._final_answer_tool_name is None and self.
|
324
|
+
if self._final_answer_tool_name is None and self._exit_tool_call_loop(
|
322
325
|
conversation, ctx=ctx, num_turns=turns
|
323
326
|
):
|
324
327
|
return gen_message
|
@@ -353,7 +356,7 @@ class LLMPolicyExecutor(AutoInstanceAttributesMixin, Generic[_FinalAnswerT, CtxT
|
|
353
356
|
await self.call_tools(gen_message.tool_calls, memory=memory, ctx=ctx)
|
354
357
|
|
355
358
|
# Apply the memory management function if provided.
|
356
|
-
self.
|
359
|
+
self._manage_memory(memory, ctx=ctx, num_turns=turns)
|
357
360
|
|
358
361
|
# 4. Generate the next message based on the updated memory.
|
359
362
|
# In ReAct mode, we set tool_choice to "none" if we just called tools,
|
@@ -394,7 +397,7 @@ class LLMPolicyExecutor(AutoInstanceAttributesMixin, Generic[_FinalAnswerT, CtxT
|
|
394
397
|
while True:
|
395
398
|
conversation = memory.message_history.conversations[0]
|
396
399
|
|
397
|
-
if self._final_answer_tool_name is None and self.
|
400
|
+
if self._final_answer_tool_name is None and self._exit_tool_call_loop(
|
398
401
|
conversation, ctx=ctx, num_turns=turns
|
399
402
|
):
|
400
403
|
return
|
@@ -429,7 +432,7 @@ class LLMPolicyExecutor(AutoInstanceAttributesMixin, Generic[_FinalAnswerT, CtxT
|
|
429
432
|
):
|
430
433
|
yield tool_message_event
|
431
434
|
|
432
|
-
self.
|
435
|
+
self._manage_memory(memory, ctx=ctx, num_turns=turns)
|
433
436
|
|
434
437
|
tool_choice = (
|
435
438
|
"none" if (self._react_mode and gen_message.tool_calls) else "required"
|
@@ -458,11 +461,10 @@ class LLMPolicyExecutor(AutoInstanceAttributesMixin, Generic[_FinalAnswerT, CtxT
|
|
458
461
|
)
|
459
462
|
|
460
463
|
class FinalAnswerTool(BaseTool[self._final_answer_type, None, Any]):
|
461
|
-
name: str =
|
464
|
+
name: str = FINAL_ANSWER_TOOL_NAME
|
462
465
|
description: str = (
|
463
|
-
"You must
|
464
|
-
"
|
465
|
-
"Input arguments correspond to the final answer."
|
466
|
+
"You must call this tool to provide the final answer. "
|
467
|
+
"DO NOT output your answer before calling the tool. "
|
466
468
|
)
|
467
469
|
|
468
470
|
async def run(
|
grasp_agents/printer.py
CHANGED
@@ -135,7 +135,7 @@ class Printer:
|
|
135
135
|
elif self.color_by == "role":
|
136
136
|
tool_color = self.get_role_color(role=Role.TOOL)
|
137
137
|
logger.debug(
|
138
|
-
f"\n
|
138
|
+
f"\n<{agent_name}>[TOOL_CALL]\n{tool_call.tool_name} "
|
139
139
|
f"| {tool_call.id}\n{tool_call.tool_arguments}",
|
140
140
|
extra={"color": tool_color}, # type: ignore
|
141
141
|
)
|
grasp_agents/prompt_builder.py
CHANGED
@@ -53,14 +53,14 @@ class PromptBuilder(AutoInstanceAttributesMixin, Generic[InT_contra, CtxT]):
|
|
53
53
|
self.in_prompt_template = in_prompt_template
|
54
54
|
self.sys_args_schema = sys_args_schema
|
55
55
|
self.usr_args_schema = usr_args_schema
|
56
|
-
self.
|
57
|
-
self.
|
58
|
-
None
|
59
|
-
)
|
56
|
+
self.make_system_prompt_impl: MakeSystemPromptHandler[CtxT] | None = None
|
57
|
+
self.make_input_content_impl: (
|
58
|
+
MakeInputContentHandler[InT_contra, CtxT] | None
|
59
|
+
) = None
|
60
60
|
|
61
61
|
self._in_args_type_adapter: TypeAdapter[InT_contra] = TypeAdapter(self._in_type)
|
62
62
|
|
63
|
-
def
|
63
|
+
def make_system_prompt(
|
64
64
|
self, sys_args: LLMPromptArgs | None = None, ctx: RunContext[CtxT] | None = None
|
65
65
|
) -> str | None:
|
66
66
|
if self.sys_prompt_template is None:
|
@@ -76,16 +76,14 @@ class PromptBuilder(AutoInstanceAttributesMixin, Generic[InT_contra, CtxT]):
|
|
76
76
|
"provided."
|
77
77
|
)
|
78
78
|
|
79
|
-
if self.
|
80
|
-
return self.
|
79
|
+
if self.make_system_prompt_impl:
|
80
|
+
return self.make_system_prompt_impl(sys_args=val_sys_args, ctx=ctx)
|
81
81
|
|
82
|
-
sys_args_dict = (
|
83
|
-
val_sys_args.model_dump(exclude_unset=True) if val_sys_args else {}
|
84
|
-
)
|
82
|
+
sys_args_dict = val_sys_args.model_dump() if val_sys_args else {}
|
85
83
|
|
86
84
|
return self.sys_prompt_template.format(**sys_args_dict)
|
87
85
|
|
88
|
-
def
|
86
|
+
def make_input_content(
|
89
87
|
self,
|
90
88
|
*,
|
91
89
|
in_args: InT_contra | None,
|
@@ -97,8 +95,8 @@ class PromptBuilder(AutoInstanceAttributesMixin, Generic[InT_contra, CtxT]):
|
|
97
95
|
in_args=in_args, usr_args=usr_args
|
98
96
|
)
|
99
97
|
|
100
|
-
if self.
|
101
|
-
return self.
|
98
|
+
if self.make_input_content_impl:
|
99
|
+
return self.make_input_content_impl(
|
102
100
|
in_args=val_in_args, usr_args=val_usr_args, batch_idx=batch_idx, ctx=ctx
|
103
101
|
)
|
104
102
|
|
@@ -126,7 +124,7 @@ class PromptBuilder(AutoInstanceAttributesMixin, Generic[InT_contra, CtxT]):
|
|
126
124
|
return self._usr_messages_from_content_parts(chat_inputs)
|
127
125
|
|
128
126
|
in_content_batch = [
|
129
|
-
self.
|
127
|
+
self.make_input_content(
|
130
128
|
in_args=in_args, usr_args=usr_args, batch_idx=i, ctx=ctx
|
131
129
|
)
|
132
130
|
for i, in_args in enumerate(in_args_batch or [None])
|
@@ -208,10 +206,7 @@ class PromptBuilder(AutoInstanceAttributesMixin, Generic[InT_contra, CtxT]):
|
|
208
206
|
return formatted_args, contains_image_data
|
209
207
|
|
210
208
|
def _combine_args(
|
211
|
-
self,
|
212
|
-
*,
|
213
|
-
in_args: InT_contra | None,
|
214
|
-
usr_args: LLMPromptArgs | None,
|
209
|
+
self, *, in_args: InT_contra | None, usr_args: LLMPromptArgs | None
|
215
210
|
) -> Mapping[str, PromptArgumentType] | str:
|
216
211
|
fmt_usr_args, _ = (
|
217
212
|
self._format_pydantic_prompt_args(usr_args) if usr_args else ({}, False)
|
grasp_agents/run_context.py
CHANGED
@@ -13,8 +13,8 @@ from .usage_tracker import UsageTracker
|
|
13
13
|
|
14
14
|
|
15
15
|
class RunArgs(BaseModel):
|
16
|
-
sys: LLMPromptArgs =
|
17
|
-
usr: LLMPromptArgs =
|
16
|
+
sys: LLMPromptArgs | None = None
|
17
|
+
usr: LLMPromptArgs | None = None
|
18
18
|
|
19
19
|
model_config = ConfigDict(extra="forbid")
|
20
20
|
|
grasp_agents/utils.py
CHANGED
@@ -6,7 +6,7 @@ from collections.abc import Coroutine, Mapping
|
|
6
6
|
from datetime import UTC, datetime
|
7
7
|
from logging import getLogger
|
8
8
|
from pathlib import Path
|
9
|
-
from typing import Any, TypeVar, overload
|
9
|
+
from typing import Any, TypeVar, get_args, overload
|
10
10
|
|
11
11
|
from pydantic import TypeAdapter, ValidationError
|
12
12
|
from tqdm.autonotebook import tqdm
|
@@ -88,18 +88,24 @@ def validate_obj_from_json_or_py_string(
|
|
88
88
|
else:
|
89
89
|
_selected_adapter = adapter
|
90
90
|
|
91
|
+
_type = _selected_adapter._type # type: ignore[attr-defined]
|
92
|
+
type_args = get_args(_type)
|
93
|
+
is_str_type = (_type is str) or (len(type_args) == 1 and type_args[0] is str)
|
94
|
+
|
91
95
|
try:
|
92
|
-
if
|
93
|
-
|
96
|
+
if not is_str_type:
|
97
|
+
if from_substring:
|
98
|
+
parsed = parse_json_or_py_substring(s, return_none_on_failure=True)
|
99
|
+
else:
|
100
|
+
parsed = parse_json_or_py_string(s, return_none_on_failure=True)
|
101
|
+
if parsed is None:
|
102
|
+
parsed = s
|
94
103
|
else:
|
95
|
-
parsed = parse_json_or_py_string(s, return_none_on_failure=True)
|
96
|
-
if parsed is None:
|
97
104
|
parsed = s
|
98
105
|
return _selected_adapter.validate_python(parsed)
|
99
106
|
except (json.JSONDecodeError, ValidationError) as exc:
|
100
107
|
raise ValueError(
|
101
|
-
f"Invalid JSON or Python string:\n{s}\
|
102
|
-
f"Expected type: {_selected_adapter._type}", # type: ignore[arg-type]
|
108
|
+
f"Invalid JSON or Python string:\n{s}\nExpected type: {_type}"
|
103
109
|
) from exc
|
104
110
|
|
105
111
|
|
@@ -5,20 +5,20 @@ grasp_agents/costs_dict.yaml,sha256=2MFNWtkv5W5WSCcv1Cj13B1iQLVv5Ot9pS_KW2Gu2DA,
|
|
5
5
|
grasp_agents/generics_utils.py,sha256=5Pw3I9dlnKC2VGqYKC4ZZUO3Z_vTNT-NPFovNfPkl6I,6542
|
6
6
|
grasp_agents/grasp_logging.py,sha256=H1GYhXdQvVkmauFDZ-KDwvVmPQHZUUm9sRqX_ObK2xI,1111
|
7
7
|
grasp_agents/http_client.py,sha256=KZva2MjJjuI5ohUeU8RdTAImUnQYaqBrV2jDH8smbJw,738
|
8
|
-
grasp_agents/llm.py,sha256=
|
9
|
-
grasp_agents/llm_agent.py,sha256=
|
8
|
+
grasp_agents/llm.py,sha256=vVjELab9l0mK9bjO-IJebmmXUyUiws2fNjbXVQQNRvs,5392
|
9
|
+
grasp_agents/llm_agent.py,sha256=_Fb3PAfw5okbsybz-BsUkd4kN8K9D5Sjw3HCbDHJFGk,14697
|
10
10
|
grasp_agents/llm_agent_memory.py,sha256=kD_UIF8xVgbSgW6xN87TzkdQcbTWLB-C5ZQu1_2HLx8,1770
|
11
|
-
grasp_agents/llm_policy_executor.py,sha256=
|
11
|
+
grasp_agents/llm_policy_executor.py,sha256=PVNuAejt3S-aSGsT7HvgYHyX_cZQSvrt1aUGPdkXtE4,17847
|
12
12
|
grasp_agents/memory.py,sha256=gPkVIIF6dI_xXzarIAw9kSEnSJcfW_teUsWA2JAih94,671
|
13
13
|
grasp_agents/message_history.py,sha256=-ZNy3C1z0yQeahjqR0oIoWDMySJ7vPS19jdutibW7OE,5408
|
14
14
|
grasp_agents/packet.py,sha256=PZ1EpclniAoLk7z4ieZbWzgYH3JSRgnlTe_WfbJYG_4,707
|
15
15
|
grasp_agents/packet_pool.py,sha256=9umHbi5FwuUYYhhodSR-Z-fRR6OYiZyYEzq5d4nZFK4,3036
|
16
|
-
grasp_agents/printer.py,sha256=
|
16
|
+
grasp_agents/printer.py,sha256=M-gkLrZMg0ll9T1MRmKOQbp65niFB5ZiZbm-tUT_EYw,5464
|
17
17
|
grasp_agents/processor.py,sha256=Atd_iTQNd3Nudb4mHqt3a5AQ31QUgpbrt1Fhn1sgpSk,6708
|
18
|
-
grasp_agents/prompt_builder.py,sha256=
|
19
|
-
grasp_agents/run_context.py,sha256=
|
18
|
+
grasp_agents/prompt_builder.py,sha256=1o7eMO4FxqRrrXFCj7aQKIajty6jZbBVaUZv7qOMIoY,8414
|
19
|
+
grasp_agents/run_context.py,sha256=9CidWWCKJ8umlhkRGtg_P3JQsRpH0K3_vhUjgVon4Wk,1597
|
20
20
|
grasp_agents/usage_tracker.py,sha256=SPwv6RpdoHRuMIKE2hCAWAvDbtR3uXuhr2jpHQuKWhI,3438
|
21
|
-
grasp_agents/utils.py,sha256=
|
21
|
+
grasp_agents/utils.py,sha256=WNA5b0IkAsth0XKHEjgTY3PIHdw5L3vEsYPkyDGw8Mw,4741
|
22
22
|
grasp_agents/openai/__init__.py,sha256=wpTeew6EjhM6esHCKrEKUpwq0kygMN2QQDxYtmbRG8Y,4201
|
23
23
|
grasp_agents/openai/completion_chunk_converters.py,sha256=i-1SvIWhRKtL0K8p5pb3jjACSnyHuJHTCoZovEERpxs,2628
|
24
24
|
grasp_agents/openai/completion_converters.py,sha256=vzPEkUOX4l2hobKxZjEk_dyWfzeYesO0DlvWvNVb-Sg,2656
|
@@ -45,7 +45,7 @@ grasp_agents/workflow/looped_workflow.py,sha256=QqXclXYxsW6C8Rxkf3dRaMHi-DfCvCbj
|
|
45
45
|
grasp_agents/workflow/parallel_processor.py,sha256=Xyzs2UR_mRe2GFgzzadHOhqgMu3rFjd3GUjvmZimt_k,3505
|
46
46
|
grasp_agents/workflow/sequential_workflow.py,sha256=Pl7jl9ZVDu-rC5UMfympEaQN8iG3kZurVF5eIPG62XA,2130
|
47
47
|
grasp_agents/workflow/workflow_processor.py,sha256=2-iaDIlgNXgj-ClGbiE3fYfSv-N_qRC49Gf_dF6M_40,2640
|
48
|
-
grasp_agents-0.3.
|
49
|
-
grasp_agents-0.3.
|
50
|
-
grasp_agents-0.3.
|
51
|
-
grasp_agents-0.3.
|
48
|
+
grasp_agents-0.3.5.dist-info/METADATA,sha256=O_mAQKcTBjZB5H9UoINxgkbnQyUUJE8TBEDSmFaEBVc,6806
|
49
|
+
grasp_agents-0.3.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
50
|
+
grasp_agents-0.3.5.dist-info/licenses/LICENSE.md,sha256=-nNNdWqGB8gJ2O-peFQ2Irshv5tW5pHKyTcYkwvH7CE,1201
|
51
|
+
grasp_agents-0.3.5.dist-info/RECORD,,
|
File without changes
|
File without changes
|