blaxel 0.2.37__py3-none-any.whl → 0.2.38rc122__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 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.37"
8
- __commit__ = "a09d7ea6c786074ceaa4639ce6415958524a7a5f"
7
+ __version__ = "0.2.38.pre-122"
8
+ __commit__ = "e7e19d2c82b2b0c2a44914245734597adcc00f49"
9
9
  __sentry_dsn__ = "https://9711de13cd02b285ca4378c01de8dc30@o4508714045276160.ingest.us.sentry.io/4510461121462272"
10
10
  __all__ = ["autoload", "settings", "env"]
11
11
 
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import os
4
4
  from logging import getLogger
5
- from typing import TYPE_CHECKING, Any, Sequence
5
+ from typing import TYPE_CHECKING, Any, Dict, List, Sequence, Union
6
6
 
7
7
  from blaxel.core import bl_model as bl_model_core
8
8
  from blaxel.core import settings
@@ -20,20 +20,61 @@ if TYPE_CHECKING:
20
20
  CompletionResponseAsyncGen,
21
21
  CompletionResponseGen,
22
22
  )
23
+ from llama_index.core.llms.llm import ToolSelection
24
+ from llama_index.core.tools.types import BaseTool
25
+
26
+ # Runtime imports needed for class inheritance and construction
27
+ from llama_index.core.base.llms.types import LLMMetadata # noqa: E402
28
+ from llama_index.core.llms.function_calling import FunctionCallingLLM # noqa: E402
29
+ from pydantic import PrivateAttr # noqa: E402
23
30
 
24
31
  logger = getLogger(__name__)
25
32
 
33
+ DEFAULT_CONTEXT_WINDOW = 128000
34
+ DEFAULT_NUM_OUTPUT = 4096
35
+
36
+
37
+ class TokenRefreshingLLM(FunctionCallingLLM):
38
+ """Wrapper for LlamaIndex LLMs that refreshes token before each call.
26
39
 
27
- class TokenRefreshingWrapper:
28
- """Base wrapper class that refreshes token before each call."""
40
+ Inherits from FunctionCallingLLM to maintain type compatibility with
41
+ LlamaIndex's agents and components that validate isinstance(model, LLM).
42
+ """
43
+
44
+ _model_config_data: dict = PrivateAttr(default_factory=dict)
45
+ _wrapped: Any = PrivateAttr(default=None)
29
46
 
30
47
  def __init__(self, model_config: dict):
31
- self.model_config = model_config
32
- self.wrapped_model = self._create_model()
48
+ super().__init__()
49
+ self._model_config_data = model_config
50
+ self._wrapped = self._create_model()
51
+
52
+ @classmethod
53
+ def class_name(cls) -> str:
54
+ return "TokenRefreshingLLM"
55
+
56
+ @property
57
+ def wrapped_model(self) -> Any:
58
+ """Access the underlying wrapped LLM model."""
59
+ return self._wrapped
60
+
61
+ @property
62
+ def metadata(self) -> LLMMetadata:
63
+ """Get LLM metadata, with fallback for unknown model names."""
64
+ try:
65
+ return self._wrapped.metadata
66
+ except (ValueError, KeyError) as e:
67
+ logger.warning(f"Could not get metadata from wrapped model: {e}. Using defaults.")
68
+ return LLMMetadata(
69
+ context_window=DEFAULT_CONTEXT_WINDOW,
70
+ num_output=DEFAULT_NUM_OUTPUT,
71
+ is_chat_model=True,
72
+ model_name=self._model_config_data.get("model", "unknown"),
73
+ )
33
74
 
34
75
  def _create_model(self):
35
76
  """Create the model instance with current token."""
36
- config = self.model_config
77
+ config = self._model_config_data
37
78
  model_type = config["type"]
38
79
  model = config["model"]
39
80
  url = config["url"]
@@ -115,102 +156,106 @@ class TokenRefreshingWrapper:
115
156
 
116
157
  def _refresh_token(self):
117
158
  """Refresh the token and recreate the model if needed."""
118
- # Only refresh if using ClientCredentials (which has get_token method)
119
159
  current_token = settings.auth.token
120
160
 
121
- if hasattr(settings.auth, "get_token"):
122
- # This will trigger token refresh if needed
123
- settings.auth.get_token()
124
-
125
161
  new_token = settings.auth.token
126
162
 
127
- # If token changed, recreate the model
128
163
  if current_token != new_token:
129
- self.wrapped_model = self._create_model()
164
+ self._wrapped = self._create_model()
130
165
 
131
- def __getattr__(self, name):
132
- """Delegate attribute access to wrapped model."""
133
- return getattr(self.wrapped_model, name)
166
+ # --- Core LLM methods with token refresh ---
134
167
 
168
+ def chat(self, messages: Sequence[ChatMessage], **kwargs: Any) -> ChatResponse:
169
+ self._refresh_token()
170
+ return self._wrapped.chat(messages, **kwargs)
135
171
 
136
- class TokenRefreshingLLM(TokenRefreshingWrapper):
137
- """Wrapper for LlamaIndex LLMs that refreshes token before each call."""
138
-
139
- async def achat(
140
- self,
141
- messages: Sequence[ChatMessage],
142
- **kwargs: Any,
143
- ) -> ChatResponse:
144
- """Async chat with token refresh."""
172
+ async def achat(self, messages: Sequence[ChatMessage], **kwargs: Any) -> ChatResponse:
145
173
  self._refresh_token()
146
- return await self.wrapped_model.achat(messages, **kwargs)
174
+ return await self._wrapped.achat(messages, **kwargs)
147
175
 
148
- def chat(
149
- self,
150
- messages: Sequence[ChatMessage],
151
- **kwargs: Any,
152
- ) -> ChatResponse:
153
- """Sync chat with token refresh."""
176
+ def complete(self, prompt: str, formatted: bool = False, **kwargs: Any) -> CompletionResponse:
154
177
  self._refresh_token()
155
- return self.wrapped_model.chat(messages, **kwargs)
178
+ return self._wrapped.complete(prompt, formatted=formatted, **kwargs)
156
179
 
157
- async def astream_chat(
158
- self,
159
- messages: Sequence[ChatMessage],
160
- **kwargs: Any,
161
- ) -> ChatResponseAsyncGen:
162
- """Async stream chat with token refresh."""
180
+ async def acomplete(
181
+ self, prompt: str, formatted: bool = False, **kwargs: Any
182
+ ) -> CompletionResponse:
163
183
  self._refresh_token()
164
- async for chunk in self.wrapped_model.astream_chat(messages, **kwargs):
165
- yield chunk
184
+ return await self._wrapped.acomplete(prompt, formatted=formatted, **kwargs)
166
185
 
167
186
  def stream_chat(
168
- self,
169
- messages: Sequence[ChatMessage],
170
- **kwargs: Any,
187
+ self, messages: Sequence[ChatMessage], **kwargs: Any
171
188
  ) -> ChatResponseGen:
172
- """Sync stream chat with token refresh."""
173
189
  self._refresh_token()
174
- for chunk in self.wrapped_model.stream_chat(messages, **kwargs):
175
- yield chunk
190
+ return self._wrapped.stream_chat(messages, **kwargs)
176
191
 
177
- async def acomplete(
178
- self,
179
- prompt: str,
180
- **kwargs: Any,
181
- ) -> CompletionResponse:
182
- """Async complete with token refresh."""
192
+ async def astream_chat(
193
+ self, messages: Sequence[ChatMessage], **kwargs: Any
194
+ ) -> ChatResponseAsyncGen:
183
195
  self._refresh_token()
184
- return await self.wrapped_model.acomplete(prompt, **kwargs)
196
+ result = self._wrapped.astream_chat(messages, **kwargs)
197
+ # Handle both coroutine and async generator patterns
198
+ if hasattr(result, "__aiter__"):
199
+ return result
200
+ return await result
185
201
 
186
- def complete(
187
- self,
188
- prompt: str,
189
- **kwargs: Any,
190
- ) -> CompletionResponse:
191
- """Sync complete with token refresh."""
202
+ def stream_complete(
203
+ self, prompt: str, formatted: bool = False, **kwargs: Any
204
+ ) -> CompletionResponseGen:
192
205
  self._refresh_token()
193
- return self.wrapped_model.complete(prompt, **kwargs)
206
+ return self._wrapped.stream_complete(prompt, formatted=formatted, **kwargs)
194
207
 
195
208
  async def astream_complete(
196
- self,
197
- prompt: str,
198
- **kwargs: Any,
209
+ self, prompt: str, formatted: bool = False, **kwargs: Any
199
210
  ) -> CompletionResponseAsyncGen:
200
- """Async stream complete with token refresh."""
201
211
  self._refresh_token()
202
- async for chunk in self.wrapped_model.astream_complete(prompt, **kwargs):
203
- yield chunk
212
+ result = self._wrapped.astream_complete(prompt, formatted=formatted, **kwargs)
213
+ # Handle both coroutine and async generator patterns
214
+ if hasattr(result, "__aiter__"):
215
+ return result
216
+ return await result
204
217
 
205
- def stream_complete(
218
+ # --- FunctionCallingLLM methods (delegate to wrapped model) ---
219
+
220
+ def _prepare_chat_with_tools(
206
221
  self,
207
- prompt: str,
222
+ tools: Sequence[BaseTool],
223
+ user_msg: Union[str, ChatMessage, None] = None,
224
+ chat_history: List[ChatMessage] | None = None,
225
+ verbose: bool = False,
226
+ allow_parallel_tool_calls: bool = False,
227
+ tool_required: Any = None,
208
228
  **kwargs: Any,
209
- ) -> CompletionResponseGen:
210
- """Sync stream complete with token refresh."""
211
- self._refresh_token()
212
- for chunk in self.wrapped_model.stream_complete(prompt, **kwargs):
213
- yield chunk
229
+ ) -> Dict[str, Any]:
230
+ if hasattr(self._wrapped, "_prepare_chat_with_tools"):
231
+ return self._wrapped._prepare_chat_with_tools(
232
+ tools,
233
+ user_msg=user_msg,
234
+ chat_history=chat_history,
235
+ verbose=verbose,
236
+ allow_parallel_tool_calls=allow_parallel_tool_calls,
237
+ tool_required=tool_required,
238
+ **kwargs,
239
+ )
240
+ raise NotImplementedError(
241
+ f"The wrapped model ({type(self._wrapped).__name__}) does not support function calling"
242
+ )
243
+
244
+ def get_tool_calls_from_response(
245
+ self,
246
+ response: ChatResponse,
247
+ error_on_no_tool_call: bool = True,
248
+ **kwargs: Any,
249
+ ) -> List[ToolSelection]:
250
+ if hasattr(self._wrapped, "get_tool_calls_from_response"):
251
+ return self._wrapped.get_tool_calls_from_response(
252
+ response,
253
+ error_on_no_tool_call=error_on_no_tool_call,
254
+ **kwargs,
255
+ )
256
+ raise NotImplementedError(
257
+ f"The wrapped model ({type(self._wrapped).__name__}) does not support function calling"
258
+ )
214
259
 
215
260
 
216
261
  async def bl_model(name, **kwargs):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: blaxel
3
- Version: 0.2.37
3
+ Version: 0.2.38rc122
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
@@ -1,4 +1,4 @@
1
- blaxel/__init__.py,sha256=UGO2L0cKhLfwXPewJ7MF6x92gMzo_-lJRzE-2ApXDF0,413
1
+ blaxel/__init__.py,sha256=CJtHkLCfIuSmNEqG5afzbxuceMG5h0ve2VADXBGizWs,421
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
@@ -446,7 +446,7 @@ blaxel/livekit/model.py,sha256=Qhl3EVa4Uum1IsT3nyMxJwXrZn2eDvCyj6V8RHOaJsQ,1687
446
446
  blaxel/livekit/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
447
447
  blaxel/livekit/tools.py,sha256=QipxGDnKqma_ktzTUpKgzdp5x4bvpQnxEVoqSTBesu8,1053
448
448
  blaxel/llamaindex/__init__.py,sha256=iZ3QbZhlwKvP91ChcqSXVkpRrzurMxJoQfKdZFzE2AA,127
449
- blaxel/llamaindex/model.py,sha256=_wsCiGScqXeMHbxlRDtl6ucwQsrGGM4AGHNFBdIWu1o,7003
449
+ blaxel/llamaindex/model.py,sha256=wDWEXn2oLCjdsJ9aBN6po6-LuiSuYa3-V6SRxBMTKG0,9405
450
450
  blaxel/llamaindex/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
451
451
  blaxel/llamaindex/tools.py,sha256=5wnPX45sgLduk9fPkhQ0rHRGK3Ekrye0MJNtMdw3GII,1024
452
452
  blaxel/llamaindex/custom/cohere.py,sha256=8Kfo5BjrND6EFDZXosHNrgrg98ktvxhYG48ztaWptps,18707
@@ -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.37.dist-info/METADATA,sha256=Donv60dGoQx0kX2i5GoNSEtgifJIPLgVkhKAe5WZybY,18684
476
- blaxel-0.2.37.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
477
- blaxel-0.2.37.dist-info/licenses/LICENSE,sha256=p5PNQvpvyDT_0aYBDgmV1fFI_vAD2aSV0wWG7VTgRis,1069
478
- blaxel-0.2.37.dist-info/RECORD,,
475
+ blaxel-0.2.38rc122.dist-info/METADATA,sha256=--Hscbw_W5MLB8BsePm4W1NIyMklqQuO-jdV0EBoI1E,18689
476
+ blaxel-0.2.38rc122.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
477
+ blaxel-0.2.38rc122.dist-info/licenses/LICENSE,sha256=p5PNQvpvyDT_0aYBDgmV1fFI_vAD2aSV0wWG7VTgRis,1069
478
+ blaxel-0.2.38rc122.dist-info/RECORD,,