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 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: type | Mapping[str, type] | None = None,
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: TypeAdapter[Any] | Mapping[str, TypeAdapter[Any]]
55
- if isinstance(response_format, type):
56
- self._response_format_adapter = TypeAdapter(response_format)
57
- elif isinstance(response_format, Mapping):
58
- self._response_format_adapter = {
59
- k: TypeAdapter(v) for k, v in response_format.items()
60
- }
61
- else:
62
- self._response_format_adapter = TypeAdapter(Any)
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 tools(self) -> dict[str, BaseTool[BaseModel, Any, Any]] | None:
78
- return self._tools
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 response_format(self) -> type | Mapping[str, type] | None:
82
- return self._response_format
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] = LLMPromptArgs,
66
+ sys_args_schema: type[LLMPromptArgs] | None = None,
67
67
  # User args (static args provided via RunContext)
68
- usr_args_schema: type[LLMPromptArgs] = 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._using_default_llm_response_format: bool = False
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._using_default_llm_response_format = True
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.make_sys_prompt(
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 make_sys_prompt(
312
+ def make_system_prompt(
317
313
  self, func: MakeSystemPromptHandler[CtxT]
318
314
  ) -> MakeSystemPromptHandler[CtxT]:
319
- self._prompt_builder.make_sys_prompt_impl = func
315
+ self._prompt_builder.make_system_prompt_impl = func
320
316
 
321
317
  return func
322
318
 
323
- def make_in_content(
319
+ def make_input_content(
324
320
  self, func: MakeInputContentHandler[InT_contra, CtxT]
325
321
  ) -> MakeInputContentHandler[InT_contra, CtxT]:
326
- self._prompt_builder.make_in_content_impl = func
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._make_sys_prompt_fn is not base_cls._make_sys_prompt_fn: # noqa: SLF001
363
- self._prompt_builder.make_sys_prompt_impl = self._make_sys_prompt_fn
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._make_in_content_fn is not base_cls._make_in_content_fn: # noqa: SLF001
366
- self._prompt_builder.make_in_content_impl = self._make_in_content_fn
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._set_memory_fn is not base_cls._set_memory_fn: # noqa: SLF001
369
- self._set_memory_impl = self._set_memory_fn
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._manage_memory_fn is not base_cls._manage_memory_fn: # noqa: SLF001
372
- self._policy_executor.manage_memory_impl = self._manage_memory_fn
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._exit_tool_call_loop_fn is not base_cls._exit_tool_call_loop_fn # noqa: SLF001
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
- self._parse_output_impl: (
382
- ParseOutputHandler[InT_contra, OutT_co, CtxT] | None
383
- ) = None
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 _make_sys_prompt_fn(
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 _make_in_content_fn(
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 _set_memory_fn(
403
+ def _set_memory(
406
404
  self,
407
405
  prev_memory: LLMAgentMemory,
408
- in_args: InT_contra | Sequence[InT_contra] | None = None,
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 _exit_tool_call_loop_fn(
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 _manage_memory_fn(
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 _exit_tool_call_loop_fn(
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 _manage_memory_fn(
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._exit_tool_call_loop_fn(
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._manage_memory_fn(memory, ctx=ctx, num_turns=turns)
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._exit_tool_call_loop_fn(
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._manage_memory_fn(memory, ctx=ctx, num_turns=turns)
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 = "final_answer"
464
+ name: str = FINAL_ANSWER_TOOL_NAME
462
465
  description: str = (
463
- "You must use this tool to provide the final answer. "
464
- "Do not provide the final answer anywhere else. "
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[TOOL_CALL]<{agent_name}>\n{tool_call.tool_name} "
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
  )
@@ -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.make_sys_prompt_impl: MakeSystemPromptHandler[CtxT] | None = None
57
- self.make_in_content_impl: MakeInputContentHandler[InT_contra, CtxT] | None = (
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 make_sys_prompt(
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.make_sys_prompt_impl:
80
- return self.make_sys_prompt_impl(sys_args=val_sys_args, ctx=ctx)
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 make_in_content(
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.make_in_content_impl:
101
- return self.make_in_content_impl(
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.make_in_content(
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)
@@ -13,8 +13,8 @@ from .usage_tracker import UsageTracker
13
13
 
14
14
 
15
15
  class RunArgs(BaseModel):
16
- sys: LLMPromptArgs = Field(default_factory=LLMPromptArgs)
17
- usr: LLMPromptArgs = Field(default_factory=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 from_substring:
93
- parsed = parse_json_or_py_substring(s, return_none_on_failure=True)
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}\n"
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
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: grasp_agents
3
- Version: 0.3.2
3
+ Version: 0.3.5
4
4
  Summary: Grasp Agents Library
5
5
  License-File: LICENSE.md
6
6
  Requires-Python: <4,>=3.11.4
@@ -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=5Yn4jkBPSbGVMf1sEuYXX6YrJlYZiH7oqKLY0yQIn-U,5192
9
- grasp_agents/llm_agent.py,sha256=Ez6_SQ3yq5X0hs7-zjqgYB0RvxoIJsaf4zzS8awrDZI,14851
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=ODyxTgqtbBnTRbCanMKjcQ7ET1fYy28_f2Jh_xXxY0Y,17876
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=eVpSZMVk4ZLkV78Sgfg1euzkaS3XBCb30yJcwLMqI0w,5464
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=eW_TOVarvh5niZcNg6EpiUrR_xv_xKZ0QT04RnzCLxc,8454
19
- grasp_agents/run_context.py,sha256=0y1JDbz3hJbGiqd3EjUYagkMbEK8YlCzdErp3R2MCr0,1647
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=uOUt4LDnErp3WQ2aQesH6mkMzon1-NIsft-o6aVznJE,4522
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.2.dist-info/METADATA,sha256=y7JtyI-29EtIUDTcqDhPWGyTJJd5w2QP6EKokGQqRbY,6806
49
- grasp_agents-0.3.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
50
- grasp_agents-0.3.2.dist-info/licenses/LICENSE.md,sha256=-nNNdWqGB8gJ2O-peFQ2Irshv5tW5pHKyTcYkwvH7CE,1201
51
- grasp_agents-0.3.2.dist-info/RECORD,,
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,,