blaxel 0.2.38rc122__py3-none-any.whl → 0.2.39__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.
- blaxel/__init__.py +2 -2
- blaxel/core/authentication/clientcredentials.py +1 -2
- blaxel/core/tools/__init__.py +4 -0
- blaxel/core/volume/volume.py +4 -0
- blaxel/crewai/model.py +81 -44
- blaxel/crewai/tools.py +85 -2
- blaxel/googleadk/model.py +22 -3
- blaxel/googleadk/tools.py +25 -6
- blaxel/langgraph/custom/gemini.py +19 -12
- blaxel/langgraph/model.py +26 -18
- blaxel/langgraph/tools.py +6 -11
- blaxel/livekit/model.py +7 -2
- blaxel/livekit/tools.py +3 -1
- blaxel/llamaindex/model.py +31 -15
- blaxel/llamaindex/tools.py +6 -4
- blaxel/openai/model.py +7 -1
- blaxel/openai/tools.py +13 -3
- blaxel/pydantic/model.py +38 -24
- blaxel/pydantic/tools.py +37 -4
- {blaxel-0.2.38rc122.dist-info → blaxel-0.2.39.dist-info}/METADATA +6 -47
- {blaxel-0.2.38rc122.dist-info → blaxel-0.2.39.dist-info}/RECORD +23 -23
- {blaxel-0.2.38rc122.dist-info → blaxel-0.2.39.dist-info}/WHEEL +0 -0
- {blaxel-0.2.38rc122.dist-info → blaxel-0.2.39.dist-info}/licenses/LICENSE +0 -0
blaxel/__init__.py
CHANGED
|
@@ -4,8 +4,8 @@ from .core.common.autoload import autoload
|
|
|
4
4
|
from .core.common.env import env
|
|
5
5
|
from .core.common.settings import settings
|
|
6
6
|
|
|
7
|
-
__version__ = "0.2.
|
|
8
|
-
__commit__ = "
|
|
7
|
+
__version__ = "0.2.39"
|
|
8
|
+
__commit__ = "48d4000d429ce3ce1d6d5b4858cf15115b380f96"
|
|
9
9
|
__sentry_dsn__ = "https://9711de13cd02b285ca4378c01de8dc30@o4508714045276160.ingest.us.sentry.io/4510461121462272"
|
|
10
10
|
__all__ = ["autoload", "settings", "env"]
|
|
11
11
|
|
blaxel/core/tools/__init__.py
CHANGED
|
@@ -254,6 +254,10 @@ class PersistentMcpClient:
|
|
|
254
254
|
await self.client_exit_stack.aclose()
|
|
255
255
|
except Exception as e:
|
|
256
256
|
logger.debug(f"Error closing client exit stack: {e}")
|
|
257
|
+
# Create fresh exit stacks so that future initialize() calls
|
|
258
|
+
# don't reuse stacks tainted by old cancel scopes
|
|
259
|
+
self.session_exit_stack = AsyncExitStack()
|
|
260
|
+
self.client_exit_stack = AsyncExitStack()
|
|
257
261
|
logger.debug("WebSocket connection closed due to inactivity.")
|
|
258
262
|
|
|
259
263
|
|
blaxel/core/volume/volume.py
CHANGED
|
@@ -137,6 +137,8 @@ class VolumeCreateConfiguration:
|
|
|
137
137
|
|
|
138
138
|
|
|
139
139
|
class VolumeInstance:
|
|
140
|
+
delete: "_AsyncDeleteDescriptor"
|
|
141
|
+
|
|
140
142
|
def __init__(self, volume: Volume):
|
|
141
143
|
self.volume = volume
|
|
142
144
|
|
|
@@ -275,6 +277,8 @@ class VolumeInstance:
|
|
|
275
277
|
|
|
276
278
|
|
|
277
279
|
class SyncVolumeInstance:
|
|
280
|
+
delete: "_SyncDeleteDescriptor"
|
|
281
|
+
|
|
278
282
|
"""Synchronous volume instance for managing persistent storage."""
|
|
279
283
|
|
|
280
284
|
def __init__(self, volume: Volume):
|
blaxel/crewai/model.py
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from logging import getLogger
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import httpx
|
|
4
|
+
from crewai import LLM # type: ignore[import-not-found]
|
|
5
|
+
from crewai.llms.hooks.base import BaseInterceptor # type: ignore[import-not-found]
|
|
4
6
|
|
|
5
7
|
from blaxel.core import bl_model as bl_model_core
|
|
6
8
|
from blaxel.core import settings
|
|
@@ -8,62 +10,97 @@ from blaxel.core import settings
|
|
|
8
10
|
logger = getLogger(__name__)
|
|
9
11
|
|
|
10
12
|
|
|
11
|
-
class
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
class AuthInterceptor(BaseInterceptor[httpx.Request, httpx.Response]):
|
|
14
|
+
"""Interceptor that injects dynamic auth headers into every HTTP request.
|
|
15
|
+
|
|
16
|
+
Used for crewai native providers (OpenAI, Anthropic, Gemini, etc.)
|
|
17
|
+
where the LLM.__new__ factory returns a provider-specific instance
|
|
18
|
+
and subclass overrides are not possible.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
def on_outbound(self, message: httpx.Request) -> httpx.Request:
|
|
22
|
+
auth_headers = settings.auth.get_headers()
|
|
23
|
+
# Remove the SDK's default "Authorization: Bearer replaced" header
|
|
24
|
+
# when our auth uses a different header (e.g. X-Blaxel-Authorization with API keys)
|
|
25
|
+
if "Authorization" not in auth_headers:
|
|
26
|
+
message.headers.pop("Authorization", None)
|
|
27
|
+
message.headers.pop("authorization", None)
|
|
28
|
+
for key, value in auth_headers.items():
|
|
29
|
+
message.headers[key] = value
|
|
30
|
+
return message
|
|
31
|
+
|
|
32
|
+
def on_inbound(self, message: httpx.Response) -> httpx.Response:
|
|
33
|
+
return message
|
|
34
|
+
|
|
35
|
+
async def aon_outbound(self, message: httpx.Request) -> httpx.Request:
|
|
36
|
+
return self.on_outbound(message)
|
|
37
|
+
|
|
38
|
+
async def aon_inbound(self, message: httpx.Response) -> httpx.Response:
|
|
39
|
+
return message
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# Provider types that crewai routes to native SDK implementations.
|
|
43
|
+
# These support the interceptor mechanism for auth.
|
|
44
|
+
_NATIVE_PROVIDER_PREFIXES = {"openai", "anthropic", "gemini", "azure", "bedrock"}
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _is_native_route(provider_prefix: str) -> bool:
|
|
48
|
+
"""Check if a provider prefix will be routed to a native SDK by crewai."""
|
|
49
|
+
return provider_prefix.lower() in _NATIVE_PROVIDER_PREFIXES
|
|
15
50
|
|
|
16
51
|
|
|
17
52
|
async def bl_model(name: str, **kwargs):
|
|
18
53
|
url, type, model = await bl_model_core(name).get_parameters()
|
|
54
|
+
|
|
55
|
+
# Map blaxel model types to crewai provider prefixes and base URLs
|
|
19
56
|
if type == "mistral":
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
api_key="replaced",
|
|
23
|
-
base_url=f"{url}/v1",
|
|
24
|
-
**kwargs,
|
|
25
|
-
)
|
|
57
|
+
provider_prefix = "mistral"
|
|
58
|
+
base_url = f"{url}/v1"
|
|
26
59
|
elif type == "xai":
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
api_key="replaced",
|
|
30
|
-
base_url=f"{url}/v1",
|
|
31
|
-
**kwargs,
|
|
32
|
-
)
|
|
60
|
+
provider_prefix = "groq"
|
|
61
|
+
base_url = f"{url}/v1"
|
|
33
62
|
elif type == "deepseek":
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
api_key="replaced",
|
|
37
|
-
base_url=f"{url}/v1",
|
|
38
|
-
**kwargs,
|
|
39
|
-
)
|
|
63
|
+
provider_prefix = "openai"
|
|
64
|
+
base_url = f"{url}/v1"
|
|
40
65
|
elif type == "anthropic":
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
api_key="replaced",
|
|
44
|
-
base_url=url,
|
|
45
|
-
**kwargs,
|
|
46
|
-
)
|
|
66
|
+
provider_prefix = "anthropic"
|
|
67
|
+
base_url = url
|
|
47
68
|
elif type == "gemini":
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
api_key="replaced",
|
|
51
|
-
base_url=f"{url}/v1beta/models/{model}",
|
|
52
|
-
**kwargs,
|
|
53
|
-
)
|
|
69
|
+
provider_prefix = "gemini"
|
|
70
|
+
base_url = f"{url}/v1beta/models/{model}"
|
|
54
71
|
elif type == "cerebras":
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
api_key="replaced",
|
|
58
|
-
base_url=f"{url}/v1",
|
|
59
|
-
**kwargs,
|
|
60
|
-
)
|
|
72
|
+
provider_prefix = "cerebras"
|
|
73
|
+
base_url = f"{url}/v1"
|
|
61
74
|
else:
|
|
62
75
|
if type != "openai":
|
|
63
76
|
logger.warning(f"Model {model} is not supported by CrewAI, defaulting to OpenAI")
|
|
64
|
-
|
|
65
|
-
|
|
77
|
+
provider_prefix = "openai"
|
|
78
|
+
base_url = f"{url}/v1"
|
|
79
|
+
|
|
80
|
+
model_string = f"{provider_prefix}/{model}"
|
|
81
|
+
auth_headers = settings.auth.get_headers()
|
|
82
|
+
|
|
83
|
+
if _is_native_route(provider_prefix):
|
|
84
|
+
# Native providers: use interceptor for dynamic auth headers.
|
|
85
|
+
# Always pass api_key="replaced" because crewai's native providers
|
|
86
|
+
# require a non-None api_key. The AuthInterceptor handles stripping
|
|
87
|
+
# the dummy Authorization header and injecting the real auth.
|
|
88
|
+
return LLM(
|
|
89
|
+
model=model_string,
|
|
66
90
|
api_key="replaced",
|
|
67
|
-
base_url=
|
|
91
|
+
base_url=base_url,
|
|
92
|
+
interceptor=AuthInterceptor(),
|
|
93
|
+
**kwargs,
|
|
94
|
+
)
|
|
95
|
+
else:
|
|
96
|
+
# LiteLLM fallback: pass auth headers via extra_headers param.
|
|
97
|
+
# Omit api_key when auth uses X-Blaxel-Authorization to prevent
|
|
98
|
+
# litellm from adding "Authorization: Bearer replaced".
|
|
99
|
+
llm_api_key = "replaced" if "Authorization" in auth_headers else None
|
|
100
|
+
return LLM(
|
|
101
|
+
model=model_string,
|
|
102
|
+
api_key=llm_api_key,
|
|
103
|
+
base_url=base_url,
|
|
104
|
+
extra_headers=auth_headers,
|
|
68
105
|
**kwargs,
|
|
69
106
|
)
|
blaxel/crewai/tools.py
CHANGED
|
@@ -1,10 +1,86 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
1
3
|
from crewai.tools import BaseTool
|
|
4
|
+
from pydantic import BaseModel
|
|
2
5
|
|
|
3
6
|
from blaxel.core.tools import bl_tools as bl_tools_core
|
|
4
|
-
from blaxel.core.tools.common import create_model_from_json_schema
|
|
5
7
|
from blaxel.core.tools.types import Tool
|
|
6
8
|
|
|
7
9
|
|
|
10
|
+
def _clean_schema_for_openai(schema: dict) -> dict:
|
|
11
|
+
"""Clean JSON schema to be compatible with OpenAI strict mode.
|
|
12
|
+
|
|
13
|
+
Recursively resolves anyOf patterns, ensures all schemas have type keys,
|
|
14
|
+
removes additionalProperties and $schema, and ensures object types have
|
|
15
|
+
properties and required fields.
|
|
16
|
+
"""
|
|
17
|
+
if not isinstance(schema, dict):
|
|
18
|
+
return schema
|
|
19
|
+
|
|
20
|
+
cleaned = schema.copy()
|
|
21
|
+
|
|
22
|
+
# Remove unsupported keys
|
|
23
|
+
cleaned.pop("$schema", None)
|
|
24
|
+
cleaned.pop("additionalProperties", None)
|
|
25
|
+
|
|
26
|
+
# Resolve anyOf: pick the non-null type
|
|
27
|
+
if "anyOf" in cleaned:
|
|
28
|
+
any_of = cleaned.pop("anyOf")
|
|
29
|
+
non_null = [s for s in any_of if s.get("type") != "null"]
|
|
30
|
+
if non_null:
|
|
31
|
+
# Merge the first non-null variant into current schema
|
|
32
|
+
resolved = _clean_schema_for_openai(non_null[0])
|
|
33
|
+
cleaned.update(resolved)
|
|
34
|
+
else:
|
|
35
|
+
cleaned["type"] = "string"
|
|
36
|
+
|
|
37
|
+
# Ensure type exists
|
|
38
|
+
if "type" not in cleaned and "properties" in cleaned:
|
|
39
|
+
cleaned["type"] = "object"
|
|
40
|
+
|
|
41
|
+
# Handle object types
|
|
42
|
+
if cleaned.get("type") == "object":
|
|
43
|
+
if "properties" not in cleaned:
|
|
44
|
+
cleaned["properties"] = {}
|
|
45
|
+
if "required" not in cleaned:
|
|
46
|
+
cleaned["required"] = list(cleaned["properties"].keys())
|
|
47
|
+
|
|
48
|
+
# Recursively clean properties
|
|
49
|
+
if "properties" in cleaned:
|
|
50
|
+
cleaned["properties"] = {
|
|
51
|
+
k: _clean_schema_for_openai(v) for k, v in cleaned["properties"].items()
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
# Recursively clean array items
|
|
55
|
+
if "items" in cleaned:
|
|
56
|
+
cleaned["items"] = _clean_schema_for_openai(cleaned["items"])
|
|
57
|
+
# Ensure items has a type
|
|
58
|
+
if "type" not in cleaned["items"]:
|
|
59
|
+
cleaned["items"]["type"] = "string"
|
|
60
|
+
|
|
61
|
+
return cleaned
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _make_clean_args_schema(tool: Tool) -> type[BaseModel]:
|
|
65
|
+
"""Create a Pydantic model whose JSON schema returns the pre-cleaned schema.
|
|
66
|
+
|
|
67
|
+
CrewAI calls model_json_schema() on args_schema to build the OpenAI tool
|
|
68
|
+
parameters. By overriding model_json_schema we ensure the cleaned schema
|
|
69
|
+
is used directly, avoiding issues with Pydantic re-introducing anyOf or
|
|
70
|
+
dropping type keys on array items.
|
|
71
|
+
"""
|
|
72
|
+
clean = _clean_schema_for_openai(tool.input_schema)
|
|
73
|
+
|
|
74
|
+
class CleanArgsSchema(BaseModel):
|
|
75
|
+
@classmethod
|
|
76
|
+
def model_json_schema(cls, *args: Any, **kwargs: Any) -> dict[str, Any]:
|
|
77
|
+
return clean
|
|
78
|
+
|
|
79
|
+
CleanArgsSchema.__name__ = f"{tool.name}Schema"
|
|
80
|
+
CleanArgsSchema.__qualname__ = f"{tool.name}Schema"
|
|
81
|
+
return CleanArgsSchema
|
|
82
|
+
|
|
83
|
+
|
|
8
84
|
class CrewAITool(BaseTool):
|
|
9
85
|
_tool: Tool
|
|
10
86
|
|
|
@@ -12,13 +88,20 @@ class CrewAITool(BaseTool):
|
|
|
12
88
|
super().__init__(
|
|
13
89
|
name=tool.name,
|
|
14
90
|
description=tool.description,
|
|
15
|
-
args_schema=
|
|
91
|
+
args_schema=_make_clean_args_schema(tool),
|
|
16
92
|
)
|
|
17
93
|
self._tool = tool
|
|
18
94
|
|
|
19
95
|
def _run(self, *args, **kwargs):
|
|
96
|
+
if not self._tool.sync_coroutine:
|
|
97
|
+
raise ValueError(f"Tool {self._tool.name} does not have a sync_coroutine defined")
|
|
20
98
|
return self._tool.sync_coroutine(**kwargs)
|
|
21
99
|
|
|
100
|
+
async def _arun(self, *args, **kwargs):
|
|
101
|
+
if not self._tool.coroutine:
|
|
102
|
+
raise ValueError(f"Tool {self._tool.name} does not have a coroutine defined")
|
|
103
|
+
return await self._tool.coroutine(**kwargs)
|
|
104
|
+
|
|
22
105
|
|
|
23
106
|
async def bl_tools(tools_names: list[str], **kwargs) -> list[BaseTool]:
|
|
24
107
|
tools = bl_tools_core(tools_names, **kwargs)
|
blaxel/googleadk/model.py
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
from logging import getLogger
|
|
2
2
|
|
|
3
|
-
from google.adk.models.lite_llm import
|
|
3
|
+
from google.adk.models.lite_llm import ( # type: ignore[import-not-found]
|
|
4
|
+
LiteLlm,
|
|
5
|
+
LiteLLMClient,
|
|
6
|
+
)
|
|
4
7
|
|
|
5
8
|
from blaxel.core import bl_model as bl_model_core
|
|
6
9
|
from blaxel.core import settings
|
|
@@ -23,7 +26,15 @@ class AuthenticatedLiteLLMClient(LiteLLMClient):
|
|
|
23
26
|
Returns:
|
|
24
27
|
The model response as a message.
|
|
25
28
|
"""
|
|
26
|
-
|
|
29
|
+
auth_headers = settings.auth.get_headers()
|
|
30
|
+
extra = dict(auth_headers)
|
|
31
|
+
# When auth uses X-Blaxel-Authorization (API keys), override the
|
|
32
|
+
# Authorization header that litellm sets from api_key or OPENAI_API_KEY
|
|
33
|
+
# env var. Without this, the server sees an invalid Authorization header
|
|
34
|
+
# and rejects the request.
|
|
35
|
+
if "Authorization" not in auth_headers:
|
|
36
|
+
extra["Authorization"] = ""
|
|
37
|
+
kwargs["extra_headers"] = extra
|
|
27
38
|
return await super().acompletion(
|
|
28
39
|
model=model,
|
|
29
40
|
messages=messages,
|
|
@@ -44,7 +55,15 @@ class AuthenticatedLiteLLMClient(LiteLLMClient):
|
|
|
44
55
|
Returns:
|
|
45
56
|
The response from the model.
|
|
46
57
|
"""
|
|
47
|
-
|
|
58
|
+
auth_headers = settings.auth.get_headers()
|
|
59
|
+
extra = dict(auth_headers)
|
|
60
|
+
# When auth uses X-Blaxel-Authorization (API keys), override the
|
|
61
|
+
# Authorization header that litellm sets from api_key or OPENAI_API_KEY
|
|
62
|
+
# env var. Without this, the server sees an invalid Authorization header
|
|
63
|
+
# and rejects the request.
|
|
64
|
+
if "Authorization" not in auth_headers:
|
|
65
|
+
extra["Authorization"] = ""
|
|
66
|
+
kwargs["extra_headers"] = extra
|
|
48
67
|
return super().completion(
|
|
49
68
|
model=model,
|
|
50
69
|
messages=messages,
|
blaxel/googleadk/tools.py
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import inspect
|
|
2
|
-
from typing import Any
|
|
2
|
+
from typing import Any
|
|
3
3
|
|
|
4
|
-
from google.adk.tools import BaseTool, ToolContext
|
|
5
|
-
from google.genai import types
|
|
4
|
+
from google.adk.tools import BaseTool, ToolContext # type: ignore[import-not-found]
|
|
5
|
+
from google.genai import types # type: ignore[import-not-found]
|
|
6
6
|
|
|
7
7
|
from blaxel.core.tools import bl_tools as bl_tools_core
|
|
8
8
|
from blaxel.core.tools.types import Tool
|
|
@@ -31,15 +31,33 @@ class GoogleADKTool(BaseTool):
|
|
|
31
31
|
if "additionalProperties" in cleaned_schema:
|
|
32
32
|
del cleaned_schema["additionalProperties"]
|
|
33
33
|
|
|
34
|
+
# Google genai Schema expects type as a single enum string (e.g. "STRING"),
|
|
35
|
+
# not a JSON Schema union list like ["null", "string"].
|
|
36
|
+
if "type" in cleaned_schema and isinstance(cleaned_schema["type"], list):
|
|
37
|
+
type_list = [t for t in cleaned_schema["type"] if t != "null"]
|
|
38
|
+
cleaned_schema["type"] = type_list[0].upper() if type_list else "STRING"
|
|
39
|
+
# Mark as nullable if "null" was in the original list
|
|
40
|
+
if "null" in schema["type"]:
|
|
41
|
+
cleaned_schema["nullable"] = True
|
|
42
|
+
elif "type" in cleaned_schema and isinstance(cleaned_schema["type"], str):
|
|
43
|
+
cleaned_schema["type"] = cleaned_schema["type"].upper()
|
|
44
|
+
|
|
45
|
+
# Ensure object types have properties
|
|
46
|
+
if cleaned_schema.get("type") == "OBJECT" and "properties" not in cleaned_schema:
|
|
47
|
+
cleaned_schema["properties"] = {}
|
|
48
|
+
|
|
34
49
|
# Recursively clean properties if they exist
|
|
35
50
|
if "properties" in cleaned_schema:
|
|
36
51
|
cleaned_schema["properties"] = {
|
|
37
52
|
k: self._clean_schema(v) for k, v in cleaned_schema["properties"].items()
|
|
38
53
|
}
|
|
39
54
|
|
|
55
|
+
# Recursively clean items for array types
|
|
56
|
+
if "items" in cleaned_schema and isinstance(cleaned_schema["items"], dict):
|
|
57
|
+
cleaned_schema["items"] = self._clean_schema(cleaned_schema["items"])
|
|
58
|
+
|
|
40
59
|
return cleaned_schema
|
|
41
60
|
|
|
42
|
-
@override
|
|
43
61
|
def _get_declaration(self) -> types.FunctionDeclaration | None:
|
|
44
62
|
# Clean the schema recursively
|
|
45
63
|
schema = self._clean_schema(self._tool.input_schema)
|
|
@@ -48,14 +66,15 @@ class GoogleADKTool(BaseTool):
|
|
|
48
66
|
types.FunctionDeclaration(
|
|
49
67
|
name=self._tool.name,
|
|
50
68
|
description=self._tool.description,
|
|
51
|
-
parameters=schema,
|
|
69
|
+
parameters=types.Schema(**schema),
|
|
52
70
|
)
|
|
53
71
|
)
|
|
54
72
|
|
|
55
73
|
return function_decl
|
|
56
74
|
|
|
57
|
-
@override
|
|
58
75
|
async def run_async(self, *, args: dict[str, Any], tool_context: ToolContext) -> Any:
|
|
76
|
+
if not self._tool.coroutine:
|
|
77
|
+
raise ValueError(f"Tool {self._tool.name} does not have a coroutine defined")
|
|
59
78
|
args_to_call = args.copy()
|
|
60
79
|
signature = inspect.signature(self._tool.coroutine)
|
|
61
80
|
if "tool_context" in signature.parameters:
|
|
@@ -23,16 +23,18 @@ from typing import (
|
|
|
23
23
|
|
|
24
24
|
import httpx
|
|
25
25
|
import requests
|
|
26
|
-
from langchain_core.callbacks.manager import (
|
|
26
|
+
from langchain_core.callbacks.manager import ( # type: ignore[import-not-found]
|
|
27
27
|
AsyncCallbackManagerForLLMRun,
|
|
28
28
|
CallbackManagerForLLMRun,
|
|
29
29
|
)
|
|
30
|
-
from langchain_core.language_models import
|
|
31
|
-
|
|
30
|
+
from langchain_core.language_models import ( # type: ignore[import-not-found]
|
|
31
|
+
LanguageModelInput,
|
|
32
|
+
)
|
|
33
|
+
from langchain_core.language_models.chat_models import ( # type: ignore[import-not-found]
|
|
32
34
|
BaseChatModel,
|
|
33
35
|
LangSmithParams,
|
|
34
36
|
)
|
|
35
|
-
from langchain_core.messages import (
|
|
37
|
+
from langchain_core.messages import ( # type: ignore[import-not-found]
|
|
36
38
|
AIMessage,
|
|
37
39
|
AIMessageChunk,
|
|
38
40
|
BaseMessage,
|
|
@@ -41,25 +43,30 @@ from langchain_core.messages import (
|
|
|
41
43
|
SystemMessage,
|
|
42
44
|
ToolMessage,
|
|
43
45
|
)
|
|
44
|
-
from langchain_core.messages.ai import UsageMetadata
|
|
45
|
-
from langchain_core.messages.tool import (
|
|
46
|
+
from langchain_core.messages.ai import UsageMetadata # type: ignore[import-not-found]
|
|
47
|
+
from langchain_core.messages.tool import ( # type: ignore[import-not-found]
|
|
46
48
|
invalid_tool_call,
|
|
47
49
|
tool_call,
|
|
48
50
|
tool_call_chunk,
|
|
49
51
|
)
|
|
50
|
-
from langchain_core.output_parsers.openai_tools import (
|
|
52
|
+
from langchain_core.output_parsers.openai_tools import ( # type: ignore[import-not-found]
|
|
51
53
|
JsonOutputKeyToolsParser,
|
|
52
54
|
PydanticToolsParser,
|
|
53
55
|
parse_tool_calls,
|
|
54
56
|
)
|
|
55
|
-
from langchain_core.outputs import (
|
|
57
|
+
from langchain_core.outputs import ( # type: ignore[import-not-found]
|
|
56
58
|
ChatGeneration,
|
|
57
59
|
ChatGenerationChunk,
|
|
58
60
|
ChatResult,
|
|
59
61
|
)
|
|
60
|
-
from langchain_core.runnables import
|
|
61
|
-
|
|
62
|
-
|
|
62
|
+
from langchain_core.runnables import ( # type: ignore[import-not-found]
|
|
63
|
+
Runnable,
|
|
64
|
+
RunnablePassthrough,
|
|
65
|
+
)
|
|
66
|
+
from langchain_core.tools import BaseTool # type: ignore[import-not-found]
|
|
67
|
+
from langchain_core.utils.function_calling import ( # type: ignore[import-not-found]
|
|
68
|
+
convert_to_openai_tool,
|
|
69
|
+
)
|
|
63
70
|
from PIL import Image
|
|
64
71
|
from pydantic import BaseModel, ConfigDict, Field, SecretStr, model_validator
|
|
65
72
|
from tenacity import (
|
|
@@ -1467,4 +1474,4 @@ def image_bytes_to_b64_string(image_bytes: bytes, image_format: str = "jpeg") ->
|
|
|
1467
1474
|
"""Convert image bytes to base64 string."""
|
|
1468
1475
|
import base64
|
|
1469
1476
|
|
|
1470
|
-
return f"data:image/{image_format};base64,{base64.b64encode(image_bytes).decode('utf-8')}"
|
|
1477
|
+
return f"data:image/{image_format};base64,{base64.b64encode(image_bytes).decode('utf-8')}"
|
blaxel/langgraph/model.py
CHANGED
|
@@ -7,11 +7,15 @@ from blaxel.core import bl_model as bl_model_core
|
|
|
7
7
|
from blaxel.core import settings
|
|
8
8
|
|
|
9
9
|
if TYPE_CHECKING:
|
|
10
|
-
from langchain_core.callbacks import Callbacks
|
|
11
|
-
from langchain_core.language_models import
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
from langchain_core.
|
|
10
|
+
from langchain_core.callbacks import Callbacks # type: ignore[import-not-found]
|
|
11
|
+
from langchain_core.language_models import ( # type: ignore[import-not-found]
|
|
12
|
+
LanguageModelInput,
|
|
13
|
+
)
|
|
14
|
+
from langchain_core.messages import BaseMessage # type: ignore[import-not-found]
|
|
15
|
+
from langchain_core.outputs import LLMResult # type: ignore[import-not-found]
|
|
16
|
+
from langchain_core.runnables import ( # type: ignore[import-not-found]
|
|
17
|
+
RunnableConfig,
|
|
18
|
+
)
|
|
15
19
|
|
|
16
20
|
logger = getLogger(__name__)
|
|
17
21
|
|
|
@@ -32,7 +36,7 @@ class TokenRefreshingWrapper:
|
|
|
32
36
|
kwargs = config.get("kwargs", {})
|
|
33
37
|
|
|
34
38
|
if model_type == "mistral":
|
|
35
|
-
from langchain_openai import ChatOpenAI
|
|
39
|
+
from langchain_openai import ChatOpenAI # type: ignore[import-not-found]
|
|
36
40
|
|
|
37
41
|
return ChatOpenAI(
|
|
38
42
|
api_key=settings.auth.token,
|
|
@@ -41,7 +45,7 @@ class TokenRefreshingWrapper:
|
|
|
41
45
|
**kwargs,
|
|
42
46
|
)
|
|
43
47
|
elif model_type == "cohere":
|
|
44
|
-
from langchain_cohere import ChatCohere
|
|
48
|
+
from langchain_cohere import ChatCohere # type: ignore[import-not-found]
|
|
45
49
|
|
|
46
50
|
return ChatCohere(
|
|
47
51
|
cohere_api_key=settings.auth.token,
|
|
@@ -50,7 +54,7 @@ class TokenRefreshingWrapper:
|
|
|
50
54
|
**kwargs,
|
|
51
55
|
)
|
|
52
56
|
elif model_type == "xai":
|
|
53
|
-
from langchain_xai import ChatXAI
|
|
57
|
+
from langchain_xai import ChatXAI # type: ignore[import-not-found]
|
|
54
58
|
|
|
55
59
|
return ChatXAI(
|
|
56
60
|
model=model,
|
|
@@ -59,7 +63,9 @@ class TokenRefreshingWrapper:
|
|
|
59
63
|
**kwargs,
|
|
60
64
|
)
|
|
61
65
|
elif model_type == "deepseek":
|
|
62
|
-
from langchain_deepseek import
|
|
66
|
+
from langchain_deepseek import ( # type: ignore[import-not-found]
|
|
67
|
+
ChatDeepSeek,
|
|
68
|
+
)
|
|
63
69
|
|
|
64
70
|
return ChatDeepSeek(
|
|
65
71
|
api_key=settings.auth.token,
|
|
@@ -68,7 +74,9 @@ class TokenRefreshingWrapper:
|
|
|
68
74
|
**kwargs,
|
|
69
75
|
)
|
|
70
76
|
elif model_type == "anthropic":
|
|
71
|
-
from langchain_anthropic import
|
|
77
|
+
from langchain_anthropic import ( # type: ignore[import-not-found]
|
|
78
|
+
ChatAnthropic,
|
|
79
|
+
)
|
|
72
80
|
|
|
73
81
|
return ChatAnthropic(
|
|
74
82
|
api_key=settings.auth.token,
|
|
@@ -78,7 +86,9 @@ class TokenRefreshingWrapper:
|
|
|
78
86
|
**kwargs,
|
|
79
87
|
)
|
|
80
88
|
elif model_type == "gemini":
|
|
81
|
-
from .custom.gemini import
|
|
89
|
+
from .custom.gemini import (
|
|
90
|
+
ChatGoogleGenerativeAI, # type: ignore[import-not-found]
|
|
91
|
+
)
|
|
82
92
|
|
|
83
93
|
return ChatGoogleGenerativeAI(
|
|
84
94
|
model=model,
|
|
@@ -88,7 +98,9 @@ class TokenRefreshingWrapper:
|
|
|
88
98
|
**kwargs,
|
|
89
99
|
)
|
|
90
100
|
elif model_type == "cerebras":
|
|
91
|
-
from langchain_cerebras import
|
|
101
|
+
from langchain_cerebras import ( # type: ignore[import-not-found]
|
|
102
|
+
ChatCerebras,
|
|
103
|
+
)
|
|
92
104
|
|
|
93
105
|
return ChatCerebras(
|
|
94
106
|
api_key=settings.auth.token,
|
|
@@ -97,7 +109,7 @@ class TokenRefreshingWrapper:
|
|
|
97
109
|
**kwargs,
|
|
98
110
|
)
|
|
99
111
|
else:
|
|
100
|
-
from langchain_openai import ChatOpenAI
|
|
112
|
+
from langchain_openai import ChatOpenAI # type: ignore[import-not-found]
|
|
101
113
|
|
|
102
114
|
if model_type != "openai":
|
|
103
115
|
logger.warning(f"Model {model} is not supported by Langchain, defaulting to OpenAI")
|
|
@@ -113,10 +125,6 @@ class TokenRefreshingWrapper:
|
|
|
113
125
|
# Only refresh if using ClientCredentials (which has get_token method)
|
|
114
126
|
current_token = settings.auth.token
|
|
115
127
|
|
|
116
|
-
if hasattr(settings.auth, "get_token"):
|
|
117
|
-
# This will trigger token refresh if needed
|
|
118
|
-
settings.auth.get_token()
|
|
119
|
-
|
|
120
128
|
new_token = settings.auth.token
|
|
121
129
|
|
|
122
130
|
# If token changed, recreate the model
|
|
@@ -251,4 +259,4 @@ async def bl_model(name: str, **kwargs):
|
|
|
251
259
|
model_config = {"type": type, "model": model, "url": url, "kwargs": kwargs}
|
|
252
260
|
|
|
253
261
|
# Create and return the wrapper
|
|
254
|
-
return TokenRefreshingChatModel(model_config)
|
|
262
|
+
return TokenRefreshingChatModel(model_config)
|
blaxel/langgraph/tools.py
CHANGED
|
@@ -4,7 +4,7 @@ from blaxel.core.tools import bl_tools as bl_tools_core
|
|
|
4
4
|
from blaxel.core.tools.types import Tool, ToolException
|
|
5
5
|
|
|
6
6
|
if TYPE_CHECKING:
|
|
7
|
-
from langchain_core.tools import StructuredTool
|
|
7
|
+
from langchain_core.tools import StructuredTool # type: ignore[import-not-found]
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
def _clean_schema_for_openai(schema: Dict[str, Any]) -> Dict[str, Any]:
|
|
@@ -37,19 +37,14 @@ def _clean_schema_for_openai(schema: Dict[str, Any]) -> Dict[str, Any]:
|
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
def get_langchain_tool(tool: Tool) -> "StructuredTool":
|
|
40
|
-
from langchain_core.tools import StructuredTool
|
|
41
|
-
from mcp.types import
|
|
42
|
-
CallToolResult,
|
|
43
|
-
EmbeddedResource,
|
|
44
|
-
ImageContent,
|
|
45
|
-
TextContent,
|
|
46
|
-
)
|
|
47
|
-
|
|
48
|
-
NonTextContent = ImageContent | EmbeddedResource
|
|
40
|
+
from langchain_core.tools import StructuredTool # type: ignore[import-not-found]
|
|
41
|
+
from mcp.types import CallToolResult, EmbeddedResource, ImageContent, TextContent
|
|
49
42
|
|
|
50
43
|
async def langchain_coroutine(
|
|
51
44
|
**arguments: dict[str, Any],
|
|
52
|
-
) -> tuple[str | list[str], list[
|
|
45
|
+
) -> tuple[str | list[str], list[ImageContent | EmbeddedResource] | None]:
|
|
46
|
+
if not tool.coroutine:
|
|
47
|
+
raise ValueError(f"Tool {tool.name} does not have a coroutine defined")
|
|
53
48
|
result: CallToolResult = await tool.coroutine(**arguments)
|
|
54
49
|
text_contents: list[TextContent] = []
|
|
55
50
|
non_text_contents = []
|
blaxel/livekit/model.py
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
from logging import getLogger
|
|
2
2
|
|
|
3
3
|
import httpx
|
|
4
|
-
from livekit.plugins import openai
|
|
5
|
-
from openai import AsyncOpenAI
|
|
4
|
+
from livekit.plugins import openai # type: ignore[import-not-found]
|
|
5
|
+
from openai import AsyncOpenAI # type: ignore[import-not-found]
|
|
6
6
|
|
|
7
7
|
from blaxel.core import bl_model as bl_model_core
|
|
8
8
|
from blaxel.core import settings
|
|
@@ -20,6 +20,11 @@ class DynamicHeadersHTTPClient(httpx.AsyncClient):
|
|
|
20
20
|
async def send(self, request, *args, **kwargs):
|
|
21
21
|
# Update headers with the latest auth headers before each request
|
|
22
22
|
auth_headers = settings.auth.get_headers()
|
|
23
|
+
# Remove the SDK's default "Authorization: Bearer replaced" header
|
|
24
|
+
# when our auth uses a different header (e.g. X-Blaxel-Authorization with API keys)
|
|
25
|
+
if "Authorization" not in auth_headers:
|
|
26
|
+
request.headers.pop("Authorization", None)
|
|
27
|
+
request.headers.pop("authorization", None)
|
|
23
28
|
for key, value in auth_headers.items():
|
|
24
29
|
request.headers[key] = value
|
|
25
30
|
return await super().send(request, *args, **kwargs)
|
blaxel/livekit/tools.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from livekit.agents import function_tool, llm
|
|
1
|
+
from livekit.agents import function_tool, llm # type: ignore[import-not-found]
|
|
2
2
|
|
|
3
3
|
from blaxel.core.tools import bl_tools as bl_tools_core
|
|
4
4
|
from blaxel.core.tools.types import Tool
|
|
@@ -6,6 +6,8 @@ from blaxel.core.tools.types import Tool
|
|
|
6
6
|
|
|
7
7
|
def livekit_coroutine(tool: Tool):
|
|
8
8
|
async def livekit_coroutine_wrapper(raw_arguments: dict[str, object]):
|
|
9
|
+
if not tool.coroutine:
|
|
10
|
+
raise ValueError(f"Tool {tool.name} does not have a coroutine defined")
|
|
9
11
|
result = await tool.coroutine(**raw_arguments)
|
|
10
12
|
return result.model_dump_json()
|
|
11
13
|
|
blaxel/llamaindex/model.py
CHANGED
|
@@ -11,7 +11,7 @@ from blaxel.core import settings
|
|
|
11
11
|
os.environ["TRANSFORMERS_NO_ADVISORY_WARNINGS"] = "1"
|
|
12
12
|
|
|
13
13
|
if TYPE_CHECKING:
|
|
14
|
-
from llama_index.core.base.llms.types import (
|
|
14
|
+
from llama_index.core.base.llms.types import ( # type: ignore[import-not-found]
|
|
15
15
|
ChatMessage,
|
|
16
16
|
ChatResponse,
|
|
17
17
|
ChatResponseAsyncGen,
|
|
@@ -20,13 +20,19 @@ if TYPE_CHECKING:
|
|
|
20
20
|
CompletionResponseAsyncGen,
|
|
21
21
|
CompletionResponseGen,
|
|
22
22
|
)
|
|
23
|
-
from llama_index.core.llms.llm import
|
|
24
|
-
|
|
23
|
+
from llama_index.core.llms.llm import ( # type: ignore[import-not-found]
|
|
24
|
+
ToolSelection,
|
|
25
|
+
)
|
|
26
|
+
from llama_index.core.tools.types import BaseTool # type: ignore[import-not-found]
|
|
25
27
|
|
|
26
28
|
# Runtime imports needed for class inheritance and construction
|
|
27
|
-
from llama_index.core.base.llms.types import
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
from llama_index.core.base.llms.types import ( # type: ignore[import-not-found]
|
|
30
|
+
LLMMetadata,
|
|
31
|
+
)
|
|
32
|
+
from llama_index.core.llms.function_calling import ( # type: ignore[import-not-found]
|
|
33
|
+
FunctionCallingLLM,
|
|
34
|
+
)
|
|
35
|
+
from pydantic import PrivateAttr # type: ignore[import-not-found]
|
|
30
36
|
|
|
31
37
|
logger = getLogger(__name__)
|
|
32
38
|
|
|
@@ -81,7 +87,9 @@ class TokenRefreshingLLM(FunctionCallingLLM):
|
|
|
81
87
|
kwargs = config.get("kwargs", {})
|
|
82
88
|
|
|
83
89
|
if model_type == "anthropic":
|
|
84
|
-
from llama_index.llms.anthropic import
|
|
90
|
+
from llama_index.llms.anthropic import ( # type: ignore[import-not-found]
|
|
91
|
+
Anthropic,
|
|
92
|
+
)
|
|
85
93
|
|
|
86
94
|
return Anthropic(
|
|
87
95
|
model=model,
|
|
@@ -91,7 +99,7 @@ class TokenRefreshingLLM(FunctionCallingLLM):
|
|
|
91
99
|
**kwargs,
|
|
92
100
|
)
|
|
93
101
|
elif model_type == "xai":
|
|
94
|
-
from llama_index.llms.groq import Groq
|
|
102
|
+
from llama_index.llms.groq import Groq # type: ignore[import-not-found]
|
|
95
103
|
|
|
96
104
|
return Groq(
|
|
97
105
|
model=model,
|
|
@@ -101,7 +109,9 @@ class TokenRefreshingLLM(FunctionCallingLLM):
|
|
|
101
109
|
)
|
|
102
110
|
elif model_type == "gemini":
|
|
103
111
|
from google.genai.types import HttpOptions
|
|
104
|
-
from llama_index.llms.google_genai import
|
|
112
|
+
from llama_index.llms.google_genai import ( # type: ignore[import-not-found]
|
|
113
|
+
GoogleGenAI,
|
|
114
|
+
)
|
|
105
115
|
|
|
106
116
|
return GoogleGenAI(
|
|
107
117
|
api_key=settings.auth.token,
|
|
@@ -114,11 +124,13 @@ class TokenRefreshingLLM(FunctionCallingLLM):
|
|
|
114
124
|
**kwargs,
|
|
115
125
|
)
|
|
116
126
|
elif model_type == "cohere":
|
|
117
|
-
from .custom.cohere import Cohere
|
|
127
|
+
from .custom.cohere import Cohere # type: ignore[import-not-found]
|
|
118
128
|
|
|
119
129
|
return Cohere(model=model, api_key=settings.auth.token, api_base=url, **kwargs)
|
|
120
130
|
elif model_type == "deepseek":
|
|
121
|
-
from llama_index.llms.deepseek import
|
|
131
|
+
from llama_index.llms.deepseek import ( # type: ignore[import-not-found]
|
|
132
|
+
DeepSeek,
|
|
133
|
+
)
|
|
122
134
|
|
|
123
135
|
return DeepSeek(
|
|
124
136
|
model=model,
|
|
@@ -127,11 +139,15 @@ class TokenRefreshingLLM(FunctionCallingLLM):
|
|
|
127
139
|
**kwargs,
|
|
128
140
|
)
|
|
129
141
|
elif model_type == "mistral":
|
|
130
|
-
from llama_index.llms.mistralai import
|
|
142
|
+
from llama_index.llms.mistralai import ( # type: ignore[import-not-found]
|
|
143
|
+
MistralAI,
|
|
144
|
+
)
|
|
131
145
|
|
|
132
146
|
return MistralAI(model=model, api_key=settings.auth.token, endpoint=url, **kwargs)
|
|
133
147
|
elif model_type == "cerebras":
|
|
134
|
-
from llama_index.llms.cerebras import
|
|
148
|
+
from llama_index.llms.cerebras import ( # type: ignore[import-not-found]
|
|
149
|
+
Cerebras,
|
|
150
|
+
)
|
|
135
151
|
|
|
136
152
|
return Cerebras(
|
|
137
153
|
model=model,
|
|
@@ -140,7 +156,7 @@ class TokenRefreshingLLM(FunctionCallingLLM):
|
|
|
140
156
|
**kwargs,
|
|
141
157
|
)
|
|
142
158
|
else:
|
|
143
|
-
from llama_index.llms.openai import OpenAI
|
|
159
|
+
from llama_index.llms.openai import OpenAI # type: ignore[import-not-found]
|
|
144
160
|
|
|
145
161
|
if model_type != "openai":
|
|
146
162
|
logger.warning(
|
|
@@ -265,4 +281,4 @@ async def bl_model(name, **kwargs):
|
|
|
265
281
|
model_config = {"type": type, "model": model, "url": url, "kwargs": kwargs}
|
|
266
282
|
|
|
267
283
|
# Create and return the wrapper
|
|
268
|
-
return TokenRefreshingLLM(model_config)
|
|
284
|
+
return TokenRefreshingLLM(model_config)
|
blaxel/llamaindex/tools.py
CHANGED
|
@@ -5,12 +5,14 @@ from blaxel.core.tools.common import create_model_from_json_schema
|
|
|
5
5
|
from blaxel.core.tools.types import Tool
|
|
6
6
|
|
|
7
7
|
if TYPE_CHECKING:
|
|
8
|
-
from llama_index.core.tools import FunctionTool
|
|
8
|
+
from llama_index.core.tools import FunctionTool # type: ignore[import-not-found]
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
def get_llamaindex_tool(tool: Tool) -> "FunctionTool":
|
|
12
|
-
from llama_index.core.tools import FunctionTool
|
|
13
|
-
from llama_index.core.tools.types import
|
|
12
|
+
from llama_index.core.tools import FunctionTool # type: ignore[import-not-found]
|
|
13
|
+
from llama_index.core.tools.types import ( # type: ignore[import-not-found]
|
|
14
|
+
ToolMetadata,
|
|
15
|
+
)
|
|
14
16
|
|
|
15
17
|
model_schema = create_model_from_json_schema(
|
|
16
18
|
tool.input_schema, model_name=f"{tool.name}_Schema"
|
|
@@ -29,4 +31,4 @@ def get_llamaindex_tool(tool: Tool) -> "FunctionTool":
|
|
|
29
31
|
async def bl_tools(tools_names: list[str], **kwargs) -> list["FunctionTool"]:
|
|
30
32
|
tools = bl_tools_core(tools_names, **kwargs)
|
|
31
33
|
await tools.initialize()
|
|
32
|
-
return [get_llamaindex_tool(tool) for tool in tools.get_tools()]
|
|
34
|
+
return [get_llamaindex_tool(tool) for tool in tools.get_tools()]
|
blaxel/openai/model.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import httpx
|
|
2
|
-
from agents import
|
|
2
|
+
from agents import OpenAIChatCompletionsModel
|
|
3
|
+
from openai import AsyncOpenAI
|
|
3
4
|
|
|
4
5
|
from blaxel.core import bl_model as bl_model_core
|
|
5
6
|
from blaxel.core import settings
|
|
@@ -14,6 +15,11 @@ class DynamicHeadersHTTPClient(httpx.AsyncClient):
|
|
|
14
15
|
async def send(self, request, *args, **kwargs):
|
|
15
16
|
# Update headers with the latest auth headers before each request
|
|
16
17
|
auth_headers = settings.auth.get_headers()
|
|
18
|
+
# Remove the SDK's default "Authorization: Bearer replaced" header
|
|
19
|
+
# when our auth uses a different header (e.g. X-Blaxel-Authorization with API keys)
|
|
20
|
+
if "Authorization" not in auth_headers:
|
|
21
|
+
request.headers.pop("Authorization", None)
|
|
22
|
+
request.headers.pop("authorization", None)
|
|
17
23
|
for key, value in auth_headers.items():
|
|
18
24
|
request.headers[key] = value
|
|
19
25
|
return await super().send(request, *args, **kwargs)
|
blaxel/openai/tools.py
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import json
|
|
2
2
|
from typing import Any
|
|
3
3
|
|
|
4
|
-
from agents import FunctionTool
|
|
4
|
+
from agents import FunctionTool # type: ignore[import-not-found]
|
|
5
|
+
from agents.tool_context import ToolContext # type: ignore[import-not-found]
|
|
5
6
|
|
|
6
7
|
from blaxel.core.tools import bl_tools as bl_tools_core
|
|
7
8
|
from blaxel.core.tools.types import Tool
|
|
@@ -24,6 +25,13 @@ def _clean_schema_for_openai(schema: dict) -> dict:
|
|
|
24
25
|
if "additionalProperties" in cleaned_schema:
|
|
25
26
|
del cleaned_schema["additionalProperties"]
|
|
26
27
|
|
|
28
|
+
# Ensure object type schemas have properties
|
|
29
|
+
if cleaned_schema.get("type") == "object":
|
|
30
|
+
if "properties" not in cleaned_schema:
|
|
31
|
+
cleaned_schema["properties"] = {}
|
|
32
|
+
if "required" not in cleaned_schema:
|
|
33
|
+
cleaned_schema["required"] = []
|
|
34
|
+
|
|
27
35
|
# Recursively clean properties if they exist
|
|
28
36
|
if "properties" in cleaned_schema:
|
|
29
37
|
cleaned_schema["properties"] = {
|
|
@@ -39,9 +47,11 @@ def _clean_schema_for_openai(schema: dict) -> dict:
|
|
|
39
47
|
|
|
40
48
|
def get_openai_tool(tool: Tool) -> FunctionTool:
|
|
41
49
|
async def openai_coroutine(
|
|
42
|
-
_:
|
|
43
|
-
arguments:
|
|
50
|
+
_: ToolContext[Any],
|
|
51
|
+
arguments: str,
|
|
44
52
|
) -> Any:
|
|
53
|
+
if not tool.coroutine:
|
|
54
|
+
raise ValueError(f"Tool {tool.name} does not have a coroutine defined")
|
|
45
55
|
result = await tool.coroutine(**json.loads(arguments))
|
|
46
56
|
return result
|
|
47
57
|
|
blaxel/pydantic/model.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from typing import Any
|
|
3
3
|
|
|
4
|
-
from pydantic_ai.models import Model
|
|
4
|
+
from pydantic_ai.models import Model # type: ignore[import-not-found]
|
|
5
5
|
|
|
6
6
|
from blaxel.core import bl_model as bl_model_core
|
|
7
7
|
from blaxel.core import settings
|
|
@@ -30,8 +30,12 @@ class TokenRefreshingModel(Model):
|
|
|
30
30
|
|
|
31
31
|
if type == "mistral":
|
|
32
32
|
from mistralai.sdk import Mistral
|
|
33
|
-
from pydantic_ai.models.mistral import
|
|
34
|
-
|
|
33
|
+
from pydantic_ai.models.mistral import ( # type: ignore[import-not-found]
|
|
34
|
+
MistralModel,
|
|
35
|
+
)
|
|
36
|
+
from pydantic_ai.providers.mistral import ( # type: ignore[import-not-found]
|
|
37
|
+
MistralProvider,
|
|
38
|
+
)
|
|
35
39
|
|
|
36
40
|
return MistralModel(
|
|
37
41
|
model_name=model,
|
|
@@ -45,8 +49,12 @@ class TokenRefreshingModel(Model):
|
|
|
45
49
|
)
|
|
46
50
|
elif type == "cohere":
|
|
47
51
|
from cohere import AsyncClientV2
|
|
48
|
-
from pydantic_ai.models.cohere import
|
|
49
|
-
|
|
52
|
+
from pydantic_ai.models.cohere import ( # type: ignore[import-not-found]
|
|
53
|
+
CohereModel,
|
|
54
|
+
)
|
|
55
|
+
from pydantic_ai.providers.cohere import ( # type: ignore[import-not-found]
|
|
56
|
+
CohereProvider,
|
|
57
|
+
)
|
|
50
58
|
|
|
51
59
|
return CohereModel(
|
|
52
60
|
model_name=model,
|
|
@@ -58,30 +66,42 @@ class TokenRefreshingModel(Model):
|
|
|
58
66
|
),
|
|
59
67
|
)
|
|
60
68
|
elif type == "xai":
|
|
61
|
-
from pydantic_ai.models.openai import
|
|
62
|
-
|
|
69
|
+
from pydantic_ai.models.openai import ( # type: ignore[import-not-found]
|
|
70
|
+
OpenAIChatModel,
|
|
71
|
+
)
|
|
72
|
+
from pydantic_ai.providers.openai import ( # type: ignore[import-not-found]
|
|
73
|
+
OpenAIProvider,
|
|
74
|
+
)
|
|
63
75
|
|
|
64
|
-
return
|
|
76
|
+
return OpenAIChatModel(
|
|
65
77
|
model_name=model,
|
|
66
78
|
provider=OpenAIProvider(
|
|
67
79
|
base_url=f"{url}/v1", api_key=settings.auth.token, **kwargs
|
|
68
80
|
),
|
|
69
81
|
)
|
|
70
82
|
elif type == "deepseek":
|
|
71
|
-
from pydantic_ai.models.openai import
|
|
72
|
-
|
|
83
|
+
from pydantic_ai.models.openai import ( # type: ignore[import-not-found]
|
|
84
|
+
OpenAIChatModel,
|
|
85
|
+
)
|
|
86
|
+
from pydantic_ai.providers.openai import ( # type: ignore[import-not-found]
|
|
87
|
+
OpenAIProvider,
|
|
88
|
+
)
|
|
73
89
|
|
|
74
|
-
return
|
|
90
|
+
return OpenAIChatModel(
|
|
75
91
|
model_name=model,
|
|
76
92
|
provider=OpenAIProvider(
|
|
77
93
|
base_url=f"{url}/v1", api_key=settings.auth.token, **kwargs
|
|
78
94
|
),
|
|
79
95
|
)
|
|
80
96
|
elif type == "cerebras":
|
|
81
|
-
from pydantic_ai.models.openai import
|
|
82
|
-
|
|
97
|
+
from pydantic_ai.models.openai import ( # type: ignore[import-not-found]
|
|
98
|
+
OpenAIChatModel,
|
|
99
|
+
)
|
|
100
|
+
from pydantic_ai.providers.openai import ( # type: ignore[import-not-found]
|
|
101
|
+
OpenAIProvider,
|
|
102
|
+
)
|
|
83
103
|
|
|
84
|
-
return
|
|
104
|
+
return OpenAIChatModel(
|
|
85
105
|
model_name=model,
|
|
86
106
|
provider=OpenAIProvider(
|
|
87
107
|
base_url=f"{url}/v1", api_key=settings.auth.token, **kwargs
|
|
@@ -116,12 +136,12 @@ class TokenRefreshingModel(Model):
|
|
|
116
136
|
),
|
|
117
137
|
)
|
|
118
138
|
else:
|
|
119
|
-
from pydantic_ai.models.openai import
|
|
139
|
+
from pydantic_ai.models.openai import OpenAIChatModel
|
|
120
140
|
from pydantic_ai.providers.openai import OpenAIProvider
|
|
121
141
|
|
|
122
142
|
if type != "openai":
|
|
123
143
|
logger.warning(f"Model {model} is not supported by Pydantic, defaulting to OpenAI")
|
|
124
|
-
return
|
|
144
|
+
return OpenAIChatModel(
|
|
125
145
|
model_name=model,
|
|
126
146
|
provider=OpenAIProvider(
|
|
127
147
|
base_url=f"{url}/v1", api_key=settings.auth.token, **kwargs
|
|
@@ -130,12 +150,6 @@ class TokenRefreshingModel(Model):
|
|
|
130
150
|
|
|
131
151
|
def _get_fresh_model(self) -> Model:
|
|
132
152
|
"""Get or create a model with fresh token if needed."""
|
|
133
|
-
# Only refresh if using ClientCredentials (which has get_token method)
|
|
134
|
-
if hasattr(settings.auth, "get_token"):
|
|
135
|
-
# This will trigger token refresh if needed
|
|
136
|
-
logger.debug(f"Calling get_token for {self.model_config['type']} model")
|
|
137
|
-
settings.auth.get_token()
|
|
138
|
-
|
|
139
153
|
new_token = settings.auth.token
|
|
140
154
|
|
|
141
155
|
# If token changed or no cached model, create new one
|
|
@@ -152,10 +166,10 @@ class TokenRefreshingModel(Model):
|
|
|
152
166
|
return model.model_name
|
|
153
167
|
|
|
154
168
|
@property
|
|
155
|
-
def system(self) ->
|
|
169
|
+
def system(self) -> str:
|
|
156
170
|
"""Return the system property from the wrapped model."""
|
|
157
171
|
model = self._get_fresh_model()
|
|
158
|
-
return model.system if hasattr(model, "system") else
|
|
172
|
+
return model.system if hasattr(model, "system") else ""
|
|
159
173
|
|
|
160
174
|
async def request(self, *args, **kwargs):
|
|
161
175
|
"""Make a request to the model with token refresh."""
|
blaxel/pydantic/tools.py
CHANGED
|
@@ -1,11 +1,44 @@
|
|
|
1
|
-
from
|
|
2
|
-
|
|
3
|
-
from pydantic_ai
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from pydantic_ai import RunContext # type: ignore[import-not-found]
|
|
4
|
+
from pydantic_ai.tools import Tool as PydanticTool # type: ignore[import-not-found]
|
|
5
|
+
from pydantic_ai.tools import ToolDefinition # type: ignore[import-not-found]
|
|
4
6
|
|
|
5
7
|
from blaxel.core.tools import Tool
|
|
6
8
|
from blaxel.core.tools import bl_tools as bl_tools_core
|
|
7
9
|
|
|
8
10
|
|
|
11
|
+
def _clean_schema_for_openai(schema: dict[str, Any]) -> dict[str, Any]:
|
|
12
|
+
"""Clean JSON schema to be compatible with OpenAI function calling.
|
|
13
|
+
|
|
14
|
+
OpenAI requires object schemas to have a 'properties' field, even if empty.
|
|
15
|
+
"""
|
|
16
|
+
if not isinstance(schema, dict):
|
|
17
|
+
return schema
|
|
18
|
+
|
|
19
|
+
cleaned = schema.copy()
|
|
20
|
+
|
|
21
|
+
if cleaned.get("type") == "object":
|
|
22
|
+
if "properties" not in cleaned:
|
|
23
|
+
cleaned["properties"] = {}
|
|
24
|
+
if "required" not in cleaned:
|
|
25
|
+
cleaned["required"] = []
|
|
26
|
+
|
|
27
|
+
if "additionalProperties" in cleaned:
|
|
28
|
+
del cleaned["additionalProperties"]
|
|
29
|
+
if "$schema" in cleaned:
|
|
30
|
+
del cleaned["$schema"]
|
|
31
|
+
|
|
32
|
+
if "properties" in cleaned:
|
|
33
|
+
cleaned["properties"] = {
|
|
34
|
+
k: _clean_schema_for_openai(v) for k, v in cleaned["properties"].items()
|
|
35
|
+
}
|
|
36
|
+
if "items" in cleaned and isinstance(cleaned["items"], dict):
|
|
37
|
+
cleaned["items"] = _clean_schema_for_openai(cleaned["items"])
|
|
38
|
+
|
|
39
|
+
return cleaned
|
|
40
|
+
|
|
41
|
+
|
|
9
42
|
def get_pydantic_tool(tool: Tool) -> PydanticTool:
|
|
10
43
|
"""
|
|
11
44
|
Converts a custom Tool object into a Pydantic AI Tool object.
|
|
@@ -27,7 +60,7 @@ def get_pydantic_tool(tool: Tool) -> PydanticTool:
|
|
|
27
60
|
"""Dynamically prepares the ToolDefinition using the custom Tool's attributes."""
|
|
28
61
|
tool_def.name = tool.name # Override inferred name
|
|
29
62
|
tool_def.description = tool.description # Override inferred description
|
|
30
|
-
tool_def.parameters_json_schema = tool.input_schema
|
|
63
|
+
tool_def.parameters_json_schema = _clean_schema_for_openai(tool.input_schema)
|
|
31
64
|
return tool_def
|
|
32
65
|
|
|
33
66
|
async def pydantic_function(**kwargs):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: blaxel
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.39
|
|
4
4
|
Summary: Blaxel - AI development platform SDK
|
|
5
5
|
Project-URL: Homepage, https://blaxel.ai
|
|
6
6
|
Project-URL: Documentation, https://docs.blaxel.ai
|
|
@@ -17,52 +17,11 @@ Requires-Dist: pyjwt>=2.0.0
|
|
|
17
17
|
Requires-Dist: python-dateutil>=2.8.0
|
|
18
18
|
Requires-Dist: pyyaml>=6.0.0
|
|
19
19
|
Requires-Dist: requests>=2.32.3
|
|
20
|
-
Requires-Dist: tomli>=2.2
|
|
20
|
+
Requires-Dist: tomli>=2.0.2
|
|
21
21
|
Requires-Dist: websockets<16.0.0
|
|
22
|
-
Provides-Extra: all
|
|
23
|
-
Requires-Dist: crewai==0.159.0; extra == 'all'
|
|
24
|
-
Requires-Dist: google-adk>=1.4.0; extra == 'all'
|
|
25
|
-
Requires-Dist: langchain-anthropic>=0.3.10; extra == 'all'
|
|
26
|
-
Requires-Dist: langchain-cerebras<0.6.0,>=0.5.0; extra == 'all'
|
|
27
|
-
Requires-Dist: langchain-cohere>=0.4.3; extra == 'all'
|
|
28
|
-
Requires-Dist: langchain-community<0.4.0,>=0.3.3; extra == 'all'
|
|
29
|
-
Requires-Dist: langchain-core<0.4.0,>=0.3.13; extra == 'all'
|
|
30
|
-
Requires-Dist: langchain-deepseek-official>=0.1.0.post1; extra == 'all'
|
|
31
|
-
Requires-Dist: langchain-openai>=0.3.10; extra == 'all'
|
|
32
|
-
Requires-Dist: langchain-xai>=0.2.2; extra == 'all'
|
|
33
|
-
Requires-Dist: langgraph<0.3.0,>=0.2.40; extra == 'all'
|
|
34
|
-
Requires-Dist: litellm==1.74.9; extra == 'all'
|
|
35
|
-
Requires-Dist: litellm>=1.63.11; extra == 'all'
|
|
36
|
-
Requires-Dist: livekit-agents[anthropic,cartesia,deepgram,elevenlabs,groq,openai,silero,turn-detector]~=1.0; extra == 'all'
|
|
37
|
-
Requires-Dist: livekit-plugins-noise-cancellation~=0.2; extra == 'all'
|
|
38
|
-
Requires-Dist: llama-index-llms-anthropic>=0.6.14; extra == 'all'
|
|
39
|
-
Requires-Dist: llama-index-llms-cerebras>=0.2.2; extra == 'all'
|
|
40
|
-
Requires-Dist: llama-index-llms-cohere>=0.4.1; extra == 'all'
|
|
41
|
-
Requires-Dist: llama-index-llms-deepseek>=0.1.1; extra == 'all'
|
|
42
|
-
Requires-Dist: llama-index-llms-google-genai>=0.1.13; extra == 'all'
|
|
43
|
-
Requires-Dist: llama-index-llms-groq>=0.3.1; extra == 'all'
|
|
44
|
-
Requires-Dist: llama-index-llms-mistralai>=0.4.0; extra == 'all'
|
|
45
|
-
Requires-Dist: llama-index-llms-openai>=0.3.42; extra == 'all'
|
|
46
|
-
Requires-Dist: llama-index>=0.12.46; extra == 'all'
|
|
47
|
-
Requires-Dist: openai-agents>=0.0.19; extra == 'all'
|
|
48
|
-
Requires-Dist: openai==1.99.9; extra == 'all'
|
|
49
|
-
Requires-Dist: opentelemetry-exporter-otlp>=1.28.0; extra == 'all'
|
|
50
|
-
Requires-Dist: opentelemetry-instrumentation-anthropic==0.41.0; extra == 'all'
|
|
51
|
-
Requires-Dist: opentelemetry-instrumentation-cohere==0.41.0; extra == 'all'
|
|
52
|
-
Requires-Dist: opentelemetry-instrumentation-crewai==0.41.0; extra == 'all'
|
|
53
|
-
Requires-Dist: opentelemetry-instrumentation-fastapi==0.56b0; extra == 'all'
|
|
54
|
-
Requires-Dist: opentelemetry-instrumentation-google-generativeai==0.41.0; extra == 'all'
|
|
55
|
-
Requires-Dist: opentelemetry-instrumentation-langchain>=0.35.0; extra == 'all'
|
|
56
|
-
Requires-Dist: opentelemetry-instrumentation-llamaindex>=0.40.7; extra == 'all'
|
|
57
|
-
Requires-Dist: opentelemetry-instrumentation-ollama==0.41.0; extra == 'all'
|
|
58
|
-
Requires-Dist: opentelemetry-instrumentation-openai==0.41.0; extra == 'all'
|
|
59
|
-
Requires-Dist: pillow>=10.0.0; extra == 'all'
|
|
60
|
-
Requires-Dist: pydantic-ai>=0.0.48; extra == 'all'
|
|
61
22
|
Provides-Extra: core
|
|
62
23
|
Provides-Extra: crewai
|
|
63
|
-
Requires-Dist: crewai==
|
|
64
|
-
Requires-Dist: litellm==1.74.9; extra == 'crewai'
|
|
65
|
-
Requires-Dist: openai==1.99.9; extra == 'crewai'
|
|
24
|
+
Requires-Dist: crewai[litellm]==1.9.3; extra == 'crewai'
|
|
66
25
|
Requires-Dist: opentelemetry-instrumentation-crewai==0.41.0; extra == 'crewai'
|
|
67
26
|
Provides-Extra: dev
|
|
68
27
|
Requires-Dist: pyright; extra == 'dev'
|
|
@@ -96,17 +55,17 @@ Requires-Dist: llama-index-llms-google-genai>=0.1.13; extra == 'llamaindex'
|
|
|
96
55
|
Requires-Dist: llama-index-llms-groq>=0.3.1; extra == 'llamaindex'
|
|
97
56
|
Requires-Dist: llama-index-llms-mistralai>=0.4.0; extra == 'llamaindex'
|
|
98
57
|
Requires-Dist: llama-index-llms-openai>=0.3.42; extra == 'llamaindex'
|
|
99
|
-
Requires-Dist: llama-index>=0.
|
|
58
|
+
Requires-Dist: llama-index>=0.14.13; extra == 'llamaindex'
|
|
100
59
|
Requires-Dist: opentelemetry-instrumentation-llamaindex>=0.40.7; extra == 'llamaindex'
|
|
101
60
|
Provides-Extra: openai
|
|
102
61
|
Requires-Dist: openai-agents>=0.0.19; extra == 'openai'
|
|
103
62
|
Provides-Extra: pydantic
|
|
104
|
-
Requires-Dist: pydantic-ai>=
|
|
63
|
+
Requires-Dist: pydantic-ai>=1.0.8; extra == 'pydantic'
|
|
105
64
|
Provides-Extra: telemetry
|
|
106
65
|
Requires-Dist: opentelemetry-exporter-otlp>=1.28.0; extra == 'telemetry'
|
|
107
66
|
Requires-Dist: opentelemetry-instrumentation-anthropic==0.41.0; extra == 'telemetry'
|
|
108
67
|
Requires-Dist: opentelemetry-instrumentation-cohere==0.41.0; extra == 'telemetry'
|
|
109
|
-
Requires-Dist: opentelemetry-instrumentation-fastapi==0.
|
|
68
|
+
Requires-Dist: opentelemetry-instrumentation-fastapi==0.55b0; extra == 'telemetry'
|
|
110
69
|
Requires-Dist: opentelemetry-instrumentation-google-generativeai==0.41.0; extra == 'telemetry'
|
|
111
70
|
Requires-Dist: opentelemetry-instrumentation-ollama==0.41.0; extra == 'telemetry'
|
|
112
71
|
Requires-Dist: opentelemetry-instrumentation-openai==0.41.0; extra == 'telemetry'
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
blaxel/__init__.py,sha256=
|
|
1
|
+
blaxel/__init__.py,sha256=QTfkxywUPHoSPf0P4W1ZlvAXblBsMkxtuduqXT78Lgo,413
|
|
2
2
|
blaxel/core/__init__.py,sha256=CU0gXpVRbuQZNWoCJuuhZS0ZhXPEu0cg-3XzoYMrBm4,1756
|
|
3
3
|
blaxel/core/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
blaxel/core/agents/__init__.py,sha256=MJZga99lU8JWUUPHd4rmUfdo7ALwWgF7CQq95SfT2OI,4456
|
|
5
5
|
blaxel/core/authentication/__init__.py,sha256=5uHv73xZ2aZRXzGHc1sP-XWqZUryfXxfC9dMX7-gd6o,3241
|
|
6
6
|
blaxel/core/authentication/apikey.py,sha256=k56FGvjoniW2BzdFqNNKzsfnu8Jvh8fvNZlwDq_78Y4,1286
|
|
7
|
-
blaxel/core/authentication/clientcredentials.py,sha256=
|
|
7
|
+
blaxel/core/authentication/clientcredentials.py,sha256=tXY-PKOMyZzqx4D-T20PJNJekUBGiEamEv8Q6W36h-g,3853
|
|
8
8
|
blaxel/core/authentication/devicemode.py,sha256=SVCBEZzL0d74JPln9lJFsngA2RsNW1RqgbORSpVbEIg,6064
|
|
9
9
|
blaxel/core/authentication/oauth.py,sha256=01yaAXytxqgsXUsSXhJzfI5-WpeU9RtrruZiimmMKf4,1453
|
|
10
10
|
blaxel/core/authentication/types.py,sha256=0AmkmiPq9THT8a9bDC645rLE8mnEKb_BHUsYmYn0JAQ,1573
|
|
@@ -423,41 +423,41 @@ blaxel/core/sandbox/sync/process.py,sha256=0sDCTBp7lANzBkzB560pJnRvRz4yopnsLYj_g
|
|
|
423
423
|
blaxel/core/sandbox/sync/sandbox.py,sha256=pbACjLaWy69imTZ2wtPA6eQeGFt5JpVuT4Fi4GPBbdU,15476
|
|
424
424
|
blaxel/core/sandbox/sync/session.py,sha256=e0CVbW2LBRYTwm4RL52S0UdNvhNfuFLo6AYE5hk9DH0,4931
|
|
425
425
|
blaxel/core/sandbox/sync/system.py,sha256=VDmO32qFVkURNZySvncYT2KBqu5Rj8cxT6qT2nMn0-k,2713
|
|
426
|
-
blaxel/core/tools/__init__.py,sha256=
|
|
426
|
+
blaxel/core/tools/__init__.py,sha256=v9Ef8MjPElJiSkq2BlS9yo0mYzyHpJCzNgW7352pcns,13391
|
|
427
427
|
blaxel/core/tools/common.py,sha256=dAjDRaI2psAoHPqKeUzyqab3N6blgkD-HO0gPMpIzCE,1878
|
|
428
428
|
blaxel/core/tools/types.py,sha256=EXa-10iOOXvd8zB2IsTS0gWrgoC2hqbIv6iK5m6E5t8,693
|
|
429
429
|
blaxel/core/volume/__init__.py,sha256=jZgddogAPJGQnD2OoTcDb9zLqxeT6yYpfC-i1yKUVUM,253
|
|
430
|
-
blaxel/core/volume/volume.py,sha256=
|
|
430
|
+
blaxel/core/volume/volume.py,sha256=jY_BrSEw063TjpX8aLIhfhKpw07NdgMMGYZIa4LhXIc,22728
|
|
431
431
|
blaxel/crewai/__init__.py,sha256=HdAZxRDgC2zW-O5xYzb_Xuysb66_fMykNJVPxlTmFnY,123
|
|
432
|
-
blaxel/crewai/model.py,sha256=
|
|
432
|
+
blaxel/crewai/model.py,sha256=mH8iKTwALRDT3IrDbiHW5zyDv9vFl0u4OX3hXPmC7mI,3973
|
|
433
433
|
blaxel/crewai/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
434
|
-
blaxel/crewai/tools.py,sha256=
|
|
434
|
+
blaxel/crewai/tools.py,sha256=Slcy1BDwzdOSa8ZHia1gSkKoQuuTHtq4nK9BLpMdlDE,3678
|
|
435
435
|
blaxel/googleadk/__init__.py,sha256=3rOLe32eQt2-YN4ktHdhDWc3TK_OW0FgidTIhZ8Nnm8,225
|
|
436
|
-
blaxel/googleadk/model.py,sha256=
|
|
436
|
+
blaxel/googleadk/model.py,sha256=vhSX7vqFtgLgwnb8dgseCmR57gZel5PwHD7WBS3Na9Y,4647
|
|
437
437
|
blaxel/googleadk/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
438
|
-
blaxel/googleadk/tools.py,sha256=
|
|
438
|
+
blaxel/googleadk/tools.py,sha256=rAdFi3nH49Onss4RFFZz4uBuq1Mx4vlywsr04a5nSF4,3510
|
|
439
439
|
blaxel/langgraph/__init__.py,sha256=lw9d7bl5TsYbemToCtus5P6XnhzR4SAcBWM-1Pffc_U,126
|
|
440
|
-
blaxel/langgraph/model.py,sha256=
|
|
440
|
+
blaxel/langgraph/model.py,sha256=SdWwhfFeYNauRIbqzb_zGgjE4oCKoUKKuZbDq-RcoOs,8578
|
|
441
441
|
blaxel/langgraph/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
442
|
-
blaxel/langgraph/tools.py,sha256=
|
|
443
|
-
blaxel/langgraph/custom/gemini.py,sha256=
|
|
442
|
+
blaxel/langgraph/tools.py,sha256=_Gw77ilq9Rhq1pmNmrFr0JItcKhvkCV4yfymW5L_lWc,2946
|
|
443
|
+
blaxel/langgraph/custom/gemini.py,sha256=Dd5GiaCDNKFxMJqd1nR54SmXf7IkSe0gu5OszE7blvk,54976
|
|
444
444
|
blaxel/livekit/__init__.py,sha256=byUwOJ6MHeSXOYXmaVoHnC3ZUmpkqJ55u5mQglXX-SQ,124
|
|
445
|
-
blaxel/livekit/model.py,sha256=
|
|
445
|
+
blaxel/livekit/model.py,sha256=ciBLX92X9SIgDcebWguO-1P4cCHMDzRXCQWesv30hmg,2080
|
|
446
446
|
blaxel/livekit/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
447
|
-
blaxel/livekit/tools.py,sha256=
|
|
447
|
+
blaxel/livekit/tools.py,sha256=2TkCkqWI1FyKR638T-B9TVWE8wNwLC0NNf4ecUERr3U,1202
|
|
448
448
|
blaxel/llamaindex/__init__.py,sha256=iZ3QbZhlwKvP91ChcqSXVkpRrzurMxJoQfKdZFzE2AA,127
|
|
449
|
-
blaxel/llamaindex/model.py,sha256=
|
|
449
|
+
blaxel/llamaindex/model.py,sha256=j0Im7BiIpu_DQes0xAIYZyiGUIsL9irsBiP88epeXBU,10038
|
|
450
450
|
blaxel/llamaindex/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
451
|
-
blaxel/llamaindex/tools.py,sha256=
|
|
451
|
+
blaxel/llamaindex/tools.py,sha256=RhAox8XT6o9FpDgXcK8Cq1hjJo-TFlgioCoVOlz_iK4,1142
|
|
452
452
|
blaxel/llamaindex/custom/cohere.py,sha256=8Kfo5BjrND6EFDZXosHNrgrg98ktvxhYG48ztaWptps,18707
|
|
453
453
|
blaxel/openai/__init__.py,sha256=YkizVtcYL2m9v-z5B1EReYVu9n9V-DCxJhSB2mvqOs0,123
|
|
454
|
-
blaxel/openai/model.py,sha256=
|
|
454
|
+
blaxel/openai/model.py,sha256=jauDHyKzAWmgjOv569F6pRGmUjxL1G9E2xGhjZhQeyQ,1587
|
|
455
455
|
blaxel/openai/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
456
|
-
blaxel/openai/tools.py,sha256=
|
|
456
|
+
blaxel/openai/tools.py,sha256=NWCrOpuJVulGegj8WI4dW48ScycPgfa6W2zrJtzZxI0,2411
|
|
457
457
|
blaxel/pydantic/__init__.py,sha256=-UDZ5VSrlgfqErJuiuphcAFwesijzXxYLeyC7yHEDrE,128
|
|
458
|
-
blaxel/pydantic/model.py,sha256=
|
|
458
|
+
blaxel/pydantic/model.py,sha256=q_FRVZ047hOolckxyp0n5pCeneWu7HvfaFF5XmA5BC0,7001
|
|
459
459
|
blaxel/pydantic/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
460
|
-
blaxel/pydantic/tools.py,sha256=
|
|
460
|
+
blaxel/pydantic/tools.py,sha256=thrSIBXeWVF3ogyfDRqK504rv2DHnK37GHI7Ze9TrM0,3091
|
|
461
461
|
blaxel/pydantic/custom/gemini.py,sha256=DddpfkP75hPPHokXWCpdk6NZiqObK5KJFxL3TXRN8Kg,1051
|
|
462
462
|
blaxel/telemetry/__init__.py,sha256=g5wNqaXAVdRmUe0cX7qKHN1cftF2MaHo_QCS4D-u8CQ,257
|
|
463
463
|
blaxel/telemetry/exporters.py,sha256=PFQ38SQYDftSmR4cGcWPhdMKo4uic6pE9qv72j6q-TE,2232
|
|
@@ -472,7 +472,7 @@ blaxel/telemetry/instrumentation/map.py,sha256=PCzZJj39yiYVYJrxLBNP-NW-tjjYyTijw
|
|
|
472
472
|
blaxel/telemetry/instrumentation/utils.py,sha256=FGyMY5ZE4f-0JdZpm_R_BCoKLJ18hftz8vsh7ftDwMk,1889
|
|
473
473
|
blaxel/telemetry/log/log.py,sha256=vtzUIFIIj4MTTKUigILDYXN8NHHPOo44OaKukpyIjQg,2407
|
|
474
474
|
blaxel/telemetry/log/logger.py,sha256=IcFWCd1yyWWGAjAd2i0pDYqpZHQ61pmcaQ7Kf4bC8lg,4150
|
|
475
|
-
blaxel-0.2.
|
|
476
|
-
blaxel-0.2.
|
|
477
|
-
blaxel-0.2.
|
|
478
|
-
blaxel-0.2.
|
|
475
|
+
blaxel-0.2.39.dist-info/METADATA,sha256=_mhXijtEXJloaPxYh4md_2i63SRdafVgWxYggj4s5_E,16109
|
|
476
|
+
blaxel-0.2.39.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
477
|
+
blaxel-0.2.39.dist-info/licenses/LICENSE,sha256=p5PNQvpvyDT_0aYBDgmV1fFI_vAD2aSV0wWG7VTgRis,1069
|
|
478
|
+
blaxel-0.2.39.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|