promptbuilder 0.4.36__py3-none-any.whl → 0.4.37__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.
@@ -319,31 +319,44 @@ 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
- response = None
325
- for response in self._create_stream(
326
- messages=messages,
327
- thinking_config=thinking_config,
328
- system_message=system_message,
329
- max_tokens=max_tokens if not autocomplete else None,
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
350
  total_count += BaseLLMClient._response_out_tokens(response)
333
351
  yield response
334
352
  finish_reason = response.candidates[0].finish_reason.value if response and response.candidates and response.candidates[0].finish_reason else None
335
353
  if finish_reason and autocomplete:
336
354
  while response.candidates and finish_reason == FinishReason.MAX_TOKENS.value:
337
- for response in self._create_stream(
338
- messages=messages,
339
- thinking_config=thinking_config,
340
- system_message=system_message,
341
- max_tokens=max_tokens if not autocomplete else None,
342
- ):
355
+ for response in _stream_factory():
343
356
  BaseLLMClient._append_generated_part(stream_messages, response)
344
357
  total_count += BaseLLMClient._response_out_tokens(response)
345
358
  yield response
346
- finish_reason = response.candidates[0].finish_reason.value if response.candidates and response.candidates[0].finish_reason else None
359
+ finish_reason = response.candidates[0].finish_reason.value if response and response.candidates and response.candidates[0].finish_reason else None
347
360
  if max_tokens is not None and total_count >= max_tokens:
348
361
  break
349
362
 
@@ -673,31 +686,41 @@ class BaseLLMClientAsync(ABC, utils.InheritDecoratorsMixin):
673
686
  max_tokens = self.default_max_tokens
674
687
 
675
688
  total_count = 0
676
- stream_iter = await self._create_stream(
677
- messages=messages,
678
- thinking_config=thinking_config,
679
- system_message=system_message,
680
- max_tokens=max_tokens if not autocomplete else None,
681
- )
682
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()
683
715
  async for response in stream_iter:
684
- BaseLLMClient._append_generated_part(messages, response)
685
- total_count += BaseLLMClient._response_out_tokens(response)
686
716
  yield response
687
-
717
+
688
718
  finish_reason = response.candidates[0].finish_reason.value if response and response.candidates and response.candidates[0].finish_reason else None
689
719
  if finish_reason and autocomplete:
690
720
  while response.candidates and finish_reason == FinishReason.MAX_TOKENS.value:
691
- stream_iter = await self._create_stream(
692
- messages=messages,
693
- thinking_config=thinking_config,
694
- system_message=system_message,
695
- max_tokens=max_tokens if not autocomplete else None,
696
- )
721
+ stream_iter = _stream_factory()
697
722
  async for response in stream_iter:
698
723
  yield response
699
- BaseLLMClient._append_generated_part(messages, response)
700
- total_count += BaseLLMClient._response_out_tokens(response)
701
724
  finish_reason = response.candidates[0].finish_reason.value if response.candidates and response.candidates[0].finish_reason else None
702
725
  if max_tokens is not None and total_count >= max_tokens:
703
726
  break
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: promptbuilder
3
- Version: 0.4.36
3
+ Version: 0.4.37
4
4
  Summary: Library for building prompts for LLMs
5
5
  Home-page: https://github.com/kapulkin/promptbuilder
6
6
  Author: Kapulkin Stanislav
@@ -9,7 +9,7 @@ promptbuilder/agent/utils.py,sha256=vTkphKw04v_QDIJtoB2JKK0RGY6iI1t_0LbmuStunzI,
9
9
  promptbuilder/llm_client/__init__.py,sha256=wJ33cnRtZX_YPsbcGxEu3SEZMOhPX7-fHI59MEPUe7I,517
10
10
  promptbuilder/llm_client/aisuite_client.py,sha256=8inY3UoH8o9yEOvRYP6a_8pjGQK0W_f9eV8MmHzpKTU,15641
11
11
  promptbuilder/llm_client/anthropic_client.py,sha256=YR1Pc4Fj0WpG7qcQnPLkQMzDsvA7SMvWomFR1oCzMsk,28328
12
- promptbuilder/llm_client/base_client.py,sha256=UZg5B4sG86QLTrdpgWw1dyd6MomEYz7i1FuMMlYtChg,33955
12
+ promptbuilder/llm_client/base_client.py,sha256=RZ7AF5b0Z8Y8WACcyhSRBe4OJFjkhsDaCkiiUYkvYIM,34852
13
13
  promptbuilder/llm_client/bedrock_client.py,sha256=IQt7Sv_Wt6mg5-bhuyr-Nwjx5Nxk2S8rKEVkfwvWqE0,28183
14
14
  promptbuilder/llm_client/config.py,sha256=exQEm35wp7lK5SfXNpN5H9VZEb2LVa4pyZ-cxGt1U-U,1124
15
15
  promptbuilder/llm_client/exceptions.py,sha256=t-X7r_a8B1jNu8eEavde1jXu5dz97yV3IG4YHOtgh0Y,4836
@@ -21,8 +21,8 @@ promptbuilder/llm_client/openai_client.py,sha256=ZgI22-j4_B6OmvV10DO1lk4yN63hNYA
21
21
  promptbuilder/llm_client/types.py,sha256=fnkSMFjK9ViaRQsD6LILpLz8R2_E1TI9efjy8VNO0RQ,8139
22
22
  promptbuilder/llm_client/utils.py,sha256=79lvSppjrrItHB5MIozbp_5Oq7TsOK4Qzt9Ae3XMLFw,7624
23
23
  promptbuilder/llm_client/vertex_client.py,sha256=OgbmRIYQXeK2kAh27ijhXuTzeg8APP38IyJ9WJqvDkY,15405
24
- promptbuilder-0.4.36.dist-info/licenses/LICENSE,sha256=fqXmInzgsvEOIaKSBgcrwKyYCGYF0MKErJ0YivtODcc,1096
25
- promptbuilder-0.4.36.dist-info/METADATA,sha256=U10TCSk-YVFDRo-tzrNI2u1TfcY6OO_Foqt2tQ-bgjs,3799
26
- promptbuilder-0.4.36.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
27
- promptbuilder-0.4.36.dist-info/top_level.txt,sha256=UBVcYn4UgrPy3O3fmmnPEU_kieuplBMgheetIMei4EI,14
28
- promptbuilder-0.4.36.dist-info/RECORD,,
24
+ promptbuilder-0.4.37.dist-info/licenses/LICENSE,sha256=fqXmInzgsvEOIaKSBgcrwKyYCGYF0MKErJ0YivtODcc,1096
25
+ promptbuilder-0.4.37.dist-info/METADATA,sha256=Qjz3KpGxhDKBbjJQpkNXLQCXNMEmAn4orrnraB6qKt4,3799
26
+ promptbuilder-0.4.37.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
27
+ promptbuilder-0.4.37.dist-info/top_level.txt,sha256=UBVcYn4UgrPy3O3fmmnPEU_kieuplBMgheetIMei4EI,14
28
+ promptbuilder-0.4.37.dist-info/RECORD,,