grasp_agents 0.5.13__tar.gz → 0.5.15__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/PKG-INFO +2 -2
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/pyproject.toml +2 -2
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/cloud_llm.py +2 -1
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/http_client.py +17 -5
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/litellm/lite_llm.py +10 -10
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/openai/openai_llm.py +1 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/processors/base_processor.py +3 -2
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/utils.py +34 -18
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/.gitignore +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/LICENSE.md +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/README.md +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/__init__.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/costs_dict.yaml +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/errors.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/generics_utils.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/grasp_logging.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/litellm/__init__.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/litellm/completion_chunk_converters.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/litellm/completion_converters.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/litellm/converters.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/litellm/message_converters.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/llm.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/llm_agent.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/llm_agent_memory.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/llm_policy_executor.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/memory.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/openai/__init__.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/openai/completion_chunk_converters.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/openai/completion_converters.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/openai/content_converters.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/openai/converters.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/openai/message_converters.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/openai/tool_converters.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/packet.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/packet_pool.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/printer.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/processors/parallel_processor.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/processors/processor.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/prompt_builder.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/rate_limiting/__init__.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/rate_limiting/rate_limiter_chunked.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/rate_limiting/types.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/rate_limiting/utils.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/run_context.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/runner.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/typing/__init__.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/typing/completion.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/typing/completion_chunk.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/typing/content.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/typing/converters.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/typing/events.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/typing/io.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/typing/message.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/typing/tool.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/usage_tracker.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/workflow/__init__.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/workflow/looped_workflow.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/workflow/sequential_workflow.py +0 -0
- {grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/workflow/workflow_processor.py +0 -0
@@ -1,12 +1,12 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: grasp_agents
|
3
|
-
Version: 0.5.
|
3
|
+
Version: 0.5.15
|
4
4
|
Summary: Grasp Agents Library
|
5
5
|
License-File: LICENSE.md
|
6
6
|
Requires-Python: <4,>=3.11.4
|
7
7
|
Requires-Dist: dotenv>=0.9.9
|
8
8
|
Requires-Dist: httpx<1,>=0.27.0
|
9
|
-
Requires-Dist: litellm>=1.
|
9
|
+
Requires-Dist: litellm>=1.76.3
|
10
10
|
Requires-Dist: openai<2,>=1.68.2
|
11
11
|
Requires-Dist: pydantic>=2
|
12
12
|
Requires-Dist: pyyaml>=6.0.2
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[project]
|
2
2
|
name = "grasp_agents"
|
3
|
-
version = "0.5.
|
3
|
+
version = "0.5.15"
|
4
4
|
description = "Grasp Agents Library"
|
5
5
|
readme = "README.md"
|
6
6
|
requires-python = ">=3.11.4,<4"
|
@@ -13,7 +13,7 @@ dependencies = [
|
|
13
13
|
"dotenv>=0.9.9",
|
14
14
|
"pyyaml>=6.0.2",
|
15
15
|
"pydantic>=2",
|
16
|
-
"litellm>=1.
|
16
|
+
"litellm>=1.76.3",
|
17
17
|
]
|
18
18
|
|
19
19
|
[dependency-groups]
|
@@ -64,6 +64,7 @@ class CloudLLM(LLM[SettingsT_co, ConvertT_co], Generic[SettingsT_co, ConvertT_co
|
|
64
64
|
api_provider: APIProvider | None = None
|
65
65
|
llm_settings: SettingsT_co | None = None
|
66
66
|
rate_limiter: LLMRateLimiter | None = None
|
67
|
+
client_timeout: float = 60.0
|
67
68
|
max_client_retries: int = 2 # HTTP client retries for network errors
|
68
69
|
max_response_retries: int = (
|
69
70
|
0 # LLM response retries: try to regenerate to pass validation
|
@@ -71,7 +72,7 @@ class CloudLLM(LLM[SettingsT_co, ConvertT_co], Generic[SettingsT_co, ConvertT_co
|
|
71
72
|
apply_response_schema_via_provider: bool = False
|
72
73
|
apply_tool_call_schema_via_provider: bool = False
|
73
74
|
async_http_client: httpx.AsyncClient | None = None
|
74
|
-
async_http_client_params:
|
75
|
+
async_http_client_params: AsyncHTTPClientParams | None = None
|
75
76
|
|
76
77
|
def __post_init__(self) -> None:
|
77
78
|
if self.rate_limiter is not None:
|
@@ -1,5 +1,3 @@
|
|
1
|
-
from typing import Any
|
2
|
-
|
3
1
|
import httpx
|
4
2
|
from pydantic import BaseModel, NonNegativeFloat, PositiveInt
|
5
3
|
|
@@ -9,13 +7,26 @@ class AsyncHTTPClientParams(BaseModel):
|
|
9
7
|
max_connections: PositiveInt = 2000
|
10
8
|
max_keepalive_connections: PositiveInt = 500
|
11
9
|
keepalive_expiry: float | None = 5
|
10
|
+
# proxy: str | None = None
|
11
|
+
# follow_redirects: bool = False
|
12
|
+
# trust_env: bool = True
|
13
|
+
# auth: AuthTypes | None = (None,)
|
14
|
+
# params: QueryParamTypes | None = (None,)
|
15
|
+
# headers: HeaderTypes | None = (None,)
|
16
|
+
# cookies: CookieTypes | None = (None,)
|
12
17
|
|
13
18
|
|
14
19
|
def create_simple_async_httpx_client(
|
15
|
-
client_params: AsyncHTTPClientParams
|
20
|
+
client_params: AsyncHTTPClientParams,
|
16
21
|
) -> httpx.AsyncClient:
|
17
|
-
|
18
|
-
|
22
|
+
extra_params = client_params.model_dump(
|
23
|
+
exclude={
|
24
|
+
"timeout",
|
25
|
+
"max_connections",
|
26
|
+
"max_keepalive_connections",
|
27
|
+
"keepalive_expiry",
|
28
|
+
}
|
29
|
+
)
|
19
30
|
return httpx.AsyncClient(
|
20
31
|
timeout=httpx.Timeout(client_params.timeout),
|
21
32
|
limits=httpx.Limits(
|
@@ -23,4 +34,5 @@ def create_simple_async_httpx_client(
|
|
23
34
|
max_keepalive_connections=client_params.max_keepalive_connections,
|
24
35
|
keepalive_expiry=client_params.keepalive_expiry,
|
25
36
|
),
|
37
|
+
**extra_params,
|
26
38
|
)
|
@@ -45,7 +45,6 @@ class LiteLLMSettings(OpenAILLMSettings, total=False):
|
|
45
45
|
class LiteLLM(CloudLLM[LiteLLMSettings, LiteLLMConverters]):
|
46
46
|
converters: LiteLLMConverters = field(default_factory=LiteLLMConverters)
|
47
47
|
|
48
|
-
timeout: float | None = None
|
49
48
|
# Drop unsupported LLM settings
|
50
49
|
drop_params: bool = True
|
51
50
|
additional_drop_params: list[str] | None = None
|
@@ -63,7 +62,7 @@ class LiteLLM(CloudLLM[LiteLLMSettings, LiteLLMConverters]):
|
|
63
62
|
self._lite_llm_completion_params.update(
|
64
63
|
{
|
65
64
|
"max_retries": self.max_client_retries,
|
66
|
-
"timeout": self.
|
65
|
+
"timeout": self.client_timeout,
|
67
66
|
"drop_params": self.drop_params,
|
68
67
|
"additional_drop_params": self.additional_drop_params,
|
69
68
|
"allowed_openai_params": self.allowed_openai_params,
|
@@ -195,14 +194,15 @@ class LiteLLM(CloudLLM[LiteLLMSettings, LiteLLMConverters]):
|
|
195
194
|
|
196
195
|
async for completion_chunk in stream:
|
197
196
|
# Fix tool call indices to be unique within each choice
|
198
|
-
|
199
|
-
for
|
200
|
-
|
201
|
-
|
202
|
-
tc.index
|
203
|
-
|
204
|
-
|
205
|
-
|
197
|
+
if completion_chunk is not None:
|
198
|
+
for n, choice in enumerate(completion_chunk.choices):
|
199
|
+
for tc in choice.delta.tool_calls or []:
|
200
|
+
# Tool call ID is not None only when it is a new tool call
|
201
|
+
if tc.id and tc.index in tc_indices[n]:
|
202
|
+
tc.index = max(tc_indices[n]) + 1
|
203
|
+
tc_indices[n].add(tc.index)
|
204
|
+
|
205
|
+
yield completion_chunk
|
206
206
|
|
207
207
|
def combine_completion_chunks(
|
208
208
|
self,
|
@@ -150,6 +150,7 @@ class OpenAILLM(CloudLLM[OpenAILLMSettings, OpenAIConverters]):
|
|
150
150
|
base_url=_api_provider.get("base_url"),
|
151
151
|
api_key=_api_provider.get("api_key"),
|
152
152
|
max_retries=self.max_client_retries,
|
153
|
+
timeout=self.client_timeout,
|
153
154
|
**_async_openai_client_params,
|
154
155
|
)
|
155
156
|
|
@@ -47,6 +47,7 @@ def with_retry(func: F) -> F:
|
|
47
47
|
async def wrapper(
|
48
48
|
self: "BaseProcessor[Any, Any, Any, Any]", *args: Any, **kwargs: Any
|
49
49
|
) -> Packet[Any]:
|
50
|
+
none_packet = Packet(payloads=[None], sender=self.name)
|
50
51
|
call_id = kwargs.get("call_id", "unknown")
|
51
52
|
for n_attempt in range(self.max_retries + 1):
|
52
53
|
try:
|
@@ -61,12 +62,12 @@ def with_retry(func: F) -> F:
|
|
61
62
|
else:
|
62
63
|
logger.warning(f"{err_message} after retrying:\n{err}")
|
63
64
|
# raise ProcRunError(proc_name=self.name, call_id=call_id) from err
|
64
|
-
return
|
65
|
+
return none_packet
|
65
66
|
|
66
67
|
logger.warning(f"{err_message} (retry attempt {n_attempt + 1}):\n{err}")
|
67
68
|
# This part should not be reachable due to the raise in the loop
|
68
69
|
# raise ProcRunError(proc_name=self.name, call_id=call_id)
|
69
|
-
return
|
70
|
+
return none_packet
|
70
71
|
|
71
72
|
return cast("F", wrapper)
|
72
73
|
|
@@ -6,7 +6,7 @@ from collections.abc import AsyncIterator, 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 Annotated, Any, TypeVar, get_args, get_origin
|
9
|
+
from typing import Annotated, Any, NoReturn, TypeVar, get_args, get_origin
|
10
10
|
|
11
11
|
from pydantic import TypeAdapter
|
12
12
|
from pydantic import ValidationError as PydanticValidationError
|
@@ -71,12 +71,15 @@ def is_str_type(t: Any) -> bool:
|
|
71
71
|
)
|
72
72
|
|
73
73
|
|
74
|
+
T = TypeVar("T")
|
75
|
+
|
76
|
+
|
74
77
|
def validate_obj_from_json_or_py_string(
|
75
78
|
s: str,
|
76
|
-
schema:
|
79
|
+
schema: type[T],
|
77
80
|
from_substring: bool = False,
|
78
81
|
strip_language_markdown: bool = True,
|
79
|
-
) ->
|
82
|
+
) -> T:
|
80
83
|
try:
|
81
84
|
if is_str_type(schema):
|
82
85
|
parsed = s
|
@@ -94,19 +97,36 @@ def validate_obj_from_json_or_py_string(
|
|
94
97
|
|
95
98
|
def validate_tagged_objs_from_json_or_py_string(
|
96
99
|
s: str,
|
97
|
-
schema_by_xml_tag: Mapping[str,
|
100
|
+
schema_by_xml_tag: Mapping[str, type[T]],
|
98
101
|
from_substring: bool = False,
|
99
102
|
strip_language_markdown: bool = True,
|
100
|
-
) -> Mapping[str,
|
101
|
-
validated_obj_per_tag: dict[str,
|
102
|
-
_schema:
|
103
|
+
) -> Mapping[str, T]:
|
104
|
+
validated_obj_per_tag: dict[str, T] = {}
|
105
|
+
_schema: type[T] | None = None
|
103
106
|
_tag: str | None = None
|
104
107
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
108
|
+
def _raise(
|
109
|
+
tag: str,
|
110
|
+
schema: Any,
|
111
|
+
*,
|
112
|
+
not_found: bool = False,
|
113
|
+
base_exc: Exception | None = None,
|
114
|
+
) -> NoReturn:
|
115
|
+
if not_found:
|
116
|
+
msg = f"Tag <{tag}> not found in string:\n{s}"
|
117
|
+
else:
|
118
|
+
msg = (
|
119
|
+
f"Failed to validate substring within tag <{tag}> against JSON schema:"
|
120
|
+
f"\n{s}\nExpected type: {schema}"
|
121
|
+
)
|
122
|
+
raise JSONSchemaValidationError(s, schema, message=msg) from base_exc
|
123
|
+
|
124
|
+
for _tag, _schema in schema_by_xml_tag.items():
|
125
|
+
match = re.search(rf"<{_tag}>\s*(.*?)\s*</{_tag}>", s, re.DOTALL)
|
126
|
+
if match is None:
|
127
|
+
continue
|
128
|
+
# _raise(_tag, _schema, not_found=True, base_exc=None)
|
129
|
+
try:
|
110
130
|
tagged_substring = match.group(1).strip()
|
111
131
|
validated_obj_per_tag[_tag] = validate_obj_from_json_or_py_string(
|
112
132
|
tagged_substring, # type: ignore[assignment]
|
@@ -114,12 +134,8 @@ def validate_tagged_objs_from_json_or_py_string(
|
|
114
134
|
from_substring=from_substring,
|
115
135
|
strip_language_markdown=strip_language_markdown,
|
116
136
|
)
|
117
|
-
|
118
|
-
|
119
|
-
f"Failed to validate substring within tag <{_tag}> against JSON schema:"
|
120
|
-
f"\n{s}\nExpected type: {_schema}"
|
121
|
-
)
|
122
|
-
raise JSONSchemaValidationError(s, _schema, message=err_message) from exc
|
137
|
+
except JSONSchemaValidationError as exc:
|
138
|
+
_raise(_tag, _schema, base_exc=exc)
|
123
139
|
|
124
140
|
return validated_obj_per_tag
|
125
141
|
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/litellm/completion_chunk_converters.py
RENAMED
File without changes
|
{grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/litellm/completion_converters.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/openai/completion_chunk_converters.py
RENAMED
File without changes
|
{grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/openai/completion_converters.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/processors/parallel_processor.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/rate_limiting/rate_limiter_chunked.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{grasp_agents-0.5.13 → grasp_agents-0.5.15}/src/grasp_agents/workflow/sequential_workflow.py
RENAMED
File without changes
|
File without changes
|