promptbuilder 0.4.35__tar.gz → 0.4.37__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.
- {promptbuilder-0.4.35/promptbuilder.egg-info → promptbuilder-0.4.37}/PKG-INFO +1 -1
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/promptbuilder/llm_client/base_client.py +74 -50
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/promptbuilder/llm_client/logfire_decorators.py +18 -22
- {promptbuilder-0.4.35 → promptbuilder-0.4.37/promptbuilder.egg-info}/PKG-INFO +1 -1
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/setup.py +1 -1
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/LICENSE +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/MANIFEST.in +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/Readme.md +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/promptbuilder/__init__.py +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/promptbuilder/agent/__init__.py +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/promptbuilder/agent/agent.py +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/promptbuilder/agent/context.py +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/promptbuilder/agent/tool.py +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/promptbuilder/agent/utils.py +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/promptbuilder/embeddings.py +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/promptbuilder/llm_client/__init__.py +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/promptbuilder/llm_client/aisuite_client.py +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/promptbuilder/llm_client/anthropic_client.py +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/promptbuilder/llm_client/bedrock_client.py +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/promptbuilder/llm_client/config.py +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/promptbuilder/llm_client/exceptions.py +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/promptbuilder/llm_client/google_client.py +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/promptbuilder/llm_client/litellm_client.py +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/promptbuilder/llm_client/main.py +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/promptbuilder/llm_client/openai_client.py +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/promptbuilder/llm_client/types.py +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/promptbuilder/llm_client/utils.py +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/promptbuilder/llm_client/vertex_client.py +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/promptbuilder/prompt_builder.py +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/promptbuilder.egg-info/SOURCES.txt +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/promptbuilder.egg-info/dependency_links.txt +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/promptbuilder.egg-info/requires.txt +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/promptbuilder.egg-info/top_level.txt +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/pyproject.toml +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/setup.cfg +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/tests/test_llm_client.py +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/tests/test_llm_client_async.py +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/tests/test_timeout_google.py +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/tests/test_timeout_litellm.py +0 -0
- {promptbuilder-0.4.35 → promptbuilder-0.4.37}/tests/test_timeout_openai.py +0 -0
|
@@ -319,34 +319,47 @@ class BaseLLMClient(ABC, utils.InheritDecoratorsMixin):
|
|
|
319
319
|
max_tokens = self.default_max_tokens
|
|
320
320
|
|
|
321
321
|
stream_messages = []
|
|
322
|
-
|
|
323
322
|
total_count = 0
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
323
|
+
response: Response | None = None
|
|
324
|
+
|
|
325
|
+
# Factory to (re)create the underlying provider stream using current accumulated state
|
|
326
|
+
def _stream_factory():
|
|
327
|
+
nonlocal response, total_count
|
|
328
|
+
tries = 3
|
|
329
|
+
while tries > 0:
|
|
330
|
+
try:
|
|
331
|
+
iter = self._create_stream(
|
|
332
|
+
messages=messages + stream_messages,
|
|
333
|
+
thinking_config=thinking_config,
|
|
334
|
+
system_message=system_message,
|
|
335
|
+
max_tokens=max_tokens if not autocomplete else None,
|
|
336
|
+
)
|
|
337
|
+
for response in iter:
|
|
338
|
+
yield response
|
|
339
|
+
break
|
|
340
|
+
except Exception as e:
|
|
341
|
+
tries -= 1
|
|
342
|
+
if tries == 0:
|
|
343
|
+
raise
|
|
344
|
+
logger.warning(f"Stream generation error: {e}, retrying...")
|
|
345
|
+
|
|
346
|
+
# Use retry to iterate through the stream; on exception previously yielded parts
|
|
347
|
+
# are already merged into stream_messages so resumed attempts continue generation.
|
|
348
|
+
for response in _stream_factory():
|
|
331
349
|
BaseLLMClient._append_generated_part(stream_messages, response)
|
|
332
|
-
finish_reason = response.candidates[0].finish_reason.value if response.candidates and response.candidates[0].finish_reason else None
|
|
333
350
|
total_count += BaseLLMClient._response_out_tokens(response)
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
total_count += BaseLLMClient._response_out_tokens(response)
|
|
347
|
-
if max_tokens is not None and total_count >= max_tokens:
|
|
348
|
-
break
|
|
349
|
-
|
|
351
|
+
yield response
|
|
352
|
+
finish_reason = response.candidates[0].finish_reason.value if response and response.candidates and response.candidates[0].finish_reason else None
|
|
353
|
+
if finish_reason and autocomplete:
|
|
354
|
+
while response.candidates and finish_reason == FinishReason.MAX_TOKENS.value:
|
|
355
|
+
for response in _stream_factory():
|
|
356
|
+
BaseLLMClient._append_generated_part(stream_messages, response)
|
|
357
|
+
total_count += BaseLLMClient._response_out_tokens(response)
|
|
358
|
+
yield response
|
|
359
|
+
finish_reason = response.candidates[0].finish_reason.value if response and response.candidates and response.candidates[0].finish_reason else None
|
|
360
|
+
if max_tokens is not None and total_count >= max_tokens:
|
|
361
|
+
break
|
|
362
|
+
|
|
350
363
|
@overload
|
|
351
364
|
def from_text(
|
|
352
365
|
self,
|
|
@@ -673,33 +686,44 @@ class BaseLLMClientAsync(ABC, utils.InheritDecoratorsMixin):
|
|
|
673
686
|
max_tokens = self.default_max_tokens
|
|
674
687
|
|
|
675
688
|
total_count = 0
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
689
|
+
response = None
|
|
690
|
+
|
|
691
|
+
async def _stream_factory():
|
|
692
|
+
nonlocal response, total_count
|
|
693
|
+
tries = 3
|
|
694
|
+
while tries > 0:
|
|
695
|
+
try:
|
|
696
|
+
iter = await self._create_stream(
|
|
697
|
+
messages=messages,
|
|
698
|
+
thinking_config=thinking_config,
|
|
699
|
+
system_message=system_message,
|
|
700
|
+
max_tokens=max_tokens if not autocomplete else None,
|
|
701
|
+
)
|
|
702
|
+
|
|
703
|
+
async for response in iter:
|
|
704
|
+
BaseLLMClient._append_generated_part(messages, response)
|
|
705
|
+
total_count += BaseLLMClient._response_out_tokens(response)
|
|
706
|
+
yield response
|
|
707
|
+
break
|
|
708
|
+
except Exception as e:
|
|
709
|
+
tries -= 1
|
|
710
|
+
if tries <= 0:
|
|
711
|
+
raise
|
|
712
|
+
logger.warning(f"Stream generation error: {e}, retrying...")
|
|
713
|
+
|
|
714
|
+
stream_iter = _stream_factory()
|
|
682
715
|
async for response in stream_iter:
|
|
683
716
|
yield response
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
max_tokens=max_tokens if not autocomplete else None,
|
|
695
|
-
)
|
|
696
|
-
async for response in stream_iter:
|
|
697
|
-
yield response
|
|
698
|
-
BaseLLMClient._append_generated_part(messages, response)
|
|
699
|
-
finish_reason = response.candidates[0].finish_reason.value if response.candidates and response.candidates[0].finish_reason else None
|
|
700
|
-
total_count += BaseLLMClient._response_out_tokens(response)
|
|
701
|
-
if max_tokens is not None and total_count >= max_tokens:
|
|
702
|
-
break
|
|
717
|
+
|
|
718
|
+
finish_reason = response.candidates[0].finish_reason.value if response and response.candidates and response.candidates[0].finish_reason else None
|
|
719
|
+
if finish_reason and autocomplete:
|
|
720
|
+
while response.candidates and finish_reason == FinishReason.MAX_TOKENS.value:
|
|
721
|
+
stream_iter = _stream_factory()
|
|
722
|
+
async for response in stream_iter:
|
|
723
|
+
yield response
|
|
724
|
+
finish_reason = response.candidates[0].finish_reason.value if response.candidates and response.candidates[0].finish_reason else None
|
|
725
|
+
if max_tokens is not None and total_count >= max_tokens:
|
|
726
|
+
break
|
|
703
727
|
|
|
704
728
|
@overload
|
|
705
729
|
async def from_text(
|
{promptbuilder-0.4.35 → promptbuilder-0.4.37}/promptbuilder/llm_client/logfire_decorators.py
RENAMED
|
@@ -54,6 +54,21 @@ def extract_response_data(response: Response) -> dict[str, Any]:
|
|
|
54
54
|
return response_data
|
|
55
55
|
|
|
56
56
|
|
|
57
|
+
def record(span: logfire.LogfireSpan, duration: float, response: Response):
|
|
58
|
+
span.set_attribute("duration", duration)
|
|
59
|
+
|
|
60
|
+
span.set_attribute("response_data", extract_response_data(response))
|
|
61
|
+
span.set_attribute("candidates", response.candidates)
|
|
62
|
+
span.set_attribute("parsed", response.parsed)
|
|
63
|
+
span.set_attribute("response_text", response.text)
|
|
64
|
+
if response.usage_metadata is not None:
|
|
65
|
+
span.set_attribute("usage_metadata.cached_content_token_count", response.usage_metadata.cached_content_token_count)
|
|
66
|
+
span.set_attribute("usage_metadata.candidates_token_count", response.usage_metadata.candidates_token_count)
|
|
67
|
+
span.set_attribute("usage_metadata.thoughts_token_count", response.usage_metadata.thoughts_token_count)
|
|
68
|
+
span.set_attribute("usage_metadata.prompt_token_count", response.usage_metadata.prompt_token_count)
|
|
69
|
+
span.set_attribute("usage_metadata.total_token_count", response.usage_metadata.total_token_count)
|
|
70
|
+
|
|
71
|
+
|
|
57
72
|
@inherited_decorator
|
|
58
73
|
def create(class_method: Callable[P, Response]) -> Callable[P, Response]:
|
|
59
74
|
"""
|
|
@@ -69,17 +84,7 @@ def create(class_method: Callable[P, Response]) -> Callable[P, Response]:
|
|
|
69
84
|
with logfire_llm.span(f"Create with {span_data["full_model_name"]}", **span_data) as span:
|
|
70
85
|
start_time = time.time()
|
|
71
86
|
response = class_method(self, *args, **kwargs)
|
|
72
|
-
span
|
|
73
|
-
|
|
74
|
-
span.set_attribute("response_data", extract_response_data(response))
|
|
75
|
-
span.set_attribute("candidates", response.candidates)
|
|
76
|
-
span.set_attribute("parsed", response.parsed)
|
|
77
|
-
span.set_attribute("response_text", response.text)
|
|
78
|
-
if response.usage_metadata is not None:
|
|
79
|
-
span.set_attribute("usage_metadata.cached_content_token_count", response.usage_metadata.cached_content_token_count)
|
|
80
|
-
span.set_attribute("usage_metadata.candidates_token_count", response.usage_metadata.candidates_token_count)
|
|
81
|
-
span.set_attribute("usage_metadata.prompt_token_count", response.usage_metadata.prompt_token_count)
|
|
82
|
-
span.set_attribute("usage_metadata.total_token_count", response.usage_metadata.total_token_count)
|
|
87
|
+
record(span, time.time() - start_time, response)
|
|
83
88
|
|
|
84
89
|
return response
|
|
85
90
|
|
|
@@ -101,17 +106,7 @@ def create_async(class_method: Callable[P, Awaitable[Response]]) -> Callable[P,
|
|
|
101
106
|
with logfire_llm.span(f"Async create with {span_data["full_model_name"]}", **span_data) as span:
|
|
102
107
|
start_time = time.time()
|
|
103
108
|
response = await class_method(self, *args, **kwargs)
|
|
104
|
-
span
|
|
105
|
-
|
|
106
|
-
span.set_attribute("response_data", extract_response_data(response))
|
|
107
|
-
span.set_attribute("candidates", response.candidates)
|
|
108
|
-
span.set_attribute("parsed", response.parsed)
|
|
109
|
-
span.set_attribute("response_text", response.text)
|
|
110
|
-
if response.usage_metadata is not None:
|
|
111
|
-
span.set_attribute("usage_metadata.cached_content_token_count", response.usage_metadata.cached_content_token_count)
|
|
112
|
-
span.set_attribute("usage_metadata.candidates_token_count", response.usage_metadata.candidates_token_count)
|
|
113
|
-
span.set_attribute("usage_metadata.prompt_token_count", response.usage_metadata.prompt_token_count)
|
|
114
|
-
span.set_attribute("usage_metadata.total_token_count", response.usage_metadata.total_token_count)
|
|
109
|
+
record(span, time.time() - start_time, response)
|
|
115
110
|
|
|
116
111
|
return response
|
|
117
112
|
|
|
@@ -150,6 +145,7 @@ def record_streaming(span: logfire.LogfireSpan):
|
|
|
150
145
|
span.set_attribute("response_text", stream_state.get_response_data()["message"]["content"])
|
|
151
146
|
span.set_attribute("usage_metadata.cached_content_token_count", stream_state.last_usage_data.cached_content_token_count)
|
|
152
147
|
span.set_attribute("usage_metadata.candidates_token_count", stream_state.last_usage_data.candidates_token_count)
|
|
148
|
+
span.set_attribute("usage_metadata.thoughts_token_count", stream_state.last_usage_data.thoughts_token_count)
|
|
153
149
|
span.set_attribute("usage_metadata.prompt_token_count", stream_state.last_usage_data.prompt_token_count)
|
|
154
150
|
span.set_attribute("usage_metadata.total_token_count", stream_state.last_usage_data.total_token_count)
|
|
155
151
|
|
|
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
|
|
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
|
|
File without changes
|