promptbuilder 0.4.17__py3-none-any.whl → 0.4.18__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.
@@ -111,13 +111,14 @@ class AnthropicLLMClient(BaseLLMClient):
111
111
  model: str,
112
112
  api_key: str = os.getenv("ANTHROPIC_API_KEY"),
113
113
  decorator_configs: DecoratorConfigs | None = None,
114
+ default_thinking_config: ThinkingConfig | None = None,
114
115
  default_max_tokens: int | None = None,
115
116
  default_max_tokens_strategy: DefaultMaxTokensStrategy = AnthropicDefaultMaxTokensStrategy(),
116
117
  **kwargs,
117
118
  ):
118
119
  if api_key is None or not isinstance(api_key, str):
119
120
  raise ValueError("To create an anthropic llm client you need to either set the environment variable ANTHROPIC_API_KEY or pass the api_key in string format")
120
- super().__init__(AnthropicLLMClient.PROVIDER, model, decorator_configs=decorator_configs, default_max_tokens=default_max_tokens)
121
+ super().__init__(AnthropicLLMClient.PROVIDER, model, decorator_configs=decorator_configs, default_thinking_config=default_thinking_config, default_max_tokens=default_max_tokens)
121
122
  self._api_key = api_key
122
123
  self.client = Anthropic(api_key=api_key)
123
124
  self.default_max_tokens_strategy = default_max_tokens_strategy
@@ -166,7 +167,7 @@ class AnthropicLLMClient(BaseLLMClient):
166
167
  messages: list[Content],
167
168
  result_type: ResultType = None,
168
169
  *,
169
- thinking_config: ThinkingConfig = ThinkingConfig(),
170
+ thinking_config: ThinkingConfig | None = None,
170
171
  system_message: str | None = None,
171
172
  max_tokens: int | None = None,
172
173
  tools: list[Tool] | None = None,
@@ -185,15 +186,18 @@ class AnthropicLLMClient(BaseLLMClient):
185
186
  "messages": anthropic_messages,
186
187
  }
187
188
 
188
- if thinking_config.include_thoughts:
189
- anthropic_kwargs["thinking"] = {
190
- "budget_tokens": thinking_config.thinking_budget,
191
- "type": "enabled",
192
- }
193
- else:
194
- anthropic_kwargs["thinking"] = {
195
- "type": "disabled",
196
- }
189
+ if thinking_config is None:
190
+ thinking_config = self.default_thinking_config
191
+ if thinking_config is not None:
192
+ if thinking_config.include_thoughts:
193
+ anthropic_kwargs["thinking"] = {
194
+ "budget_tokens": thinking_config.thinking_budget,
195
+ "type": "enabled",
196
+ }
197
+ else:
198
+ anthropic_kwargs["thinking"] = {
199
+ "type": "disabled",
200
+ }
197
201
 
198
202
  if system_message is not None:
199
203
  anthropic_kwargs["system"] = system_message
@@ -278,6 +282,7 @@ class AnthropicLLMClient(BaseLLMClient):
278
282
  self,
279
283
  messages: list[Content],
280
284
  *,
285
+ thinking_config: ThinkingConfig | None = None,
281
286
  system_message: str | None = None,
282
287
  max_tokens: int | None = None,
283
288
  ) -> Iterator[Response]:
@@ -296,6 +301,19 @@ class AnthropicLLMClient(BaseLLMClient):
296
301
  "stream": True,
297
302
  }
298
303
 
304
+ if thinking_config is None:
305
+ thinking_config = self.default_thinking_config
306
+ if thinking_config is not None:
307
+ if thinking_config.include_thoughts:
308
+ anthropic_kwargs["thinking"] = {
309
+ "budget_tokens": thinking_config.thinking_budget,
310
+ "type": "enabled",
311
+ }
312
+ else:
313
+ anthropic_kwargs["thinking"] = {
314
+ "type": "disabled",
315
+ }
316
+
299
317
  if system_message is not None:
300
318
  anthropic_kwargs["system"] = system_message
301
319
 
@@ -315,6 +333,7 @@ class AnthropicLLMClient(BaseLLMClient):
315
333
  ))
316
334
  return models
317
335
 
336
+
318
337
  class AnthropicStreamIteratorAsync:
319
338
  def __init__(self, anthropic_iterator: AsyncStream[RawMessageStreamEvent]):
320
339
  self._anthropic_iterator = anthropic_iterator
@@ -356,13 +375,14 @@ class AnthropicLLMClientAsync(BaseLLMClientAsync):
356
375
  model: str,
357
376
  api_key: str = os.getenv("ANTHROPIC_API_KEY"),
358
377
  decorator_configs: DecoratorConfigs | None = None,
378
+ default_thinking_config: ThinkingConfig | None = None,
359
379
  default_max_tokens: int | None = None,
360
380
  default_max_tokens_strategy: DefaultMaxTokensStrategy = AnthropicDefaultMaxTokensStrategy(),
361
381
  **kwargs,
362
382
  ):
363
383
  if api_key is None or not isinstance(api_key, str):
364
384
  raise ValueError("To create an anthropic llm client you need to either set the environment variable ANTHROPIC_API_KEY or pass the api_key in string format")
365
- super().__init__(AnthropicLLMClientAsync.PROVIDER, model, decorator_configs=decorator_configs, default_max_tokens=default_max_tokens)
385
+ super().__init__(AnthropicLLMClientAsync.PROVIDER, model, decorator_configs=decorator_configs, default_thinking_config=default_thinking_config, default_max_tokens=default_max_tokens)
366
386
  self._api_key = api_key
367
387
  self.client = AsyncAnthropic(api_key=api_key)
368
388
  self.default_max_tokens_strategy = default_max_tokens_strategy
@@ -376,7 +396,7 @@ class AnthropicLLMClientAsync(BaseLLMClientAsync):
376
396
  messages: list[Content],
377
397
  result_type: ResultType = None,
378
398
  *,
379
- thinking_config: ThinkingConfig = ThinkingConfig(),
399
+ thinking_config: ThinkingConfig | None = None,
380
400
  system_message: str | None = None,
381
401
  max_tokens: int | None = None,
382
402
  tools: list[Tool] | None = None,
@@ -401,15 +421,18 @@ class AnthropicLLMClientAsync(BaseLLMClientAsync):
401
421
  "messages": anthropic_messages,
402
422
  }
403
423
 
404
- if thinking_config.include_thoughts:
405
- anthropic_kwargs["thinking"] = {
406
- "budget_tokens": thinking_config.thinking_budget,
407
- "type": "enabled",
408
- }
409
- else:
410
- anthropic_kwargs["thinking"] = {
411
- "type": "disabled",
412
- }
424
+ if thinking_config is None:
425
+ thinking_config = self.default_thinking_config
426
+ if thinking_config is not None:
427
+ if thinking_config.include_thoughts:
428
+ anthropic_kwargs["thinking"] = {
429
+ "budget_tokens": thinking_config.thinking_budget,
430
+ "type": "enabled",
431
+ }
432
+ else:
433
+ anthropic_kwargs["thinking"] = {
434
+ "type": "disabled",
435
+ }
413
436
 
414
437
  if system_message is not None:
415
438
  anthropic_kwargs["system"] = system_message
@@ -494,6 +517,7 @@ class AnthropicLLMClientAsync(BaseLLMClientAsync):
494
517
  self,
495
518
  messages: list[Content],
496
519
  *,
520
+ thinking_config: ThinkingConfig | None = None,
497
521
  system_message: str | None = None,
498
522
  max_tokens: int | None = None,
499
523
  ) -> AsyncIterator[Response]:
@@ -517,6 +541,19 @@ class AnthropicLLMClientAsync(BaseLLMClientAsync):
517
541
  "stream": True,
518
542
  }
519
543
 
544
+ if thinking_config is None:
545
+ thinking_config = self.default_thinking_config
546
+ if thinking_config is not None:
547
+ if thinking_config.include_thoughts:
548
+ anthropic_kwargs["thinking"] = {
549
+ "budget_tokens": thinking_config.thinking_budget,
550
+ "type": "enabled",
551
+ }
552
+ else:
553
+ anthropic_kwargs["thinking"] = {
554
+ "type": "disabled",
555
+ }
556
+
520
557
  if system_message is not None:
521
558
  anthropic_kwargs["system"] = system_message
522
559
 
@@ -17,7 +17,15 @@ logger = logging.getLogger(__name__)
17
17
  class BaseLLMClient(ABC, utils.InheritDecoratorsMixin):
18
18
  provider: str
19
19
 
20
- def __init__(self, provider: str, model: str, decorator_configs: utils.DecoratorConfigs | None = None, default_max_tokens: int | None = None, **kwargs):
20
+ def __init__(
21
+ self,
22
+ provider: str,
23
+ model: str,
24
+ decorator_configs: utils.DecoratorConfigs | None = None,
25
+ default_thinking_config: ThinkingConfig | None = None,
26
+ default_max_tokens: int | None = None,
27
+ **kwargs,
28
+ ):
21
29
  self.provider = provider
22
30
  self.model = model
23
31
 
@@ -28,6 +36,11 @@ class BaseLLMClient(ABC, utils.InheritDecoratorsMixin):
28
36
  decorator_configs = utils.DecoratorConfigs()
29
37
  self._decorator_configs = decorator_configs
30
38
 
39
+ if default_thinking_config is None:
40
+ if self.full_model_name in GLOBAL_CONFIG.default_thinking_configs:
41
+ default_thinking_config = GLOBAL_CONFIG.default_thinking_configs[self.full_model_name]
42
+ self.default_thinking_config = default_thinking_config
43
+
31
44
  if default_max_tokens is None:
32
45
  if self.full_model_name in GLOBAL_CONFIG.default_max_tokens:
33
46
  default_max_tokens = GLOBAL_CONFIG.default_max_tokens[self.full_model_name]
@@ -69,7 +82,7 @@ class BaseLLMClient(ABC, utils.InheritDecoratorsMixin):
69
82
  messages: list[Content],
70
83
  result_type: ResultType = None,
71
84
  *,
72
- thinking_config: ThinkingConfig = ThinkingConfig(),
85
+ thinking_config: ThinkingConfig | None = None,
73
86
  system_message: str | None = None,
74
87
  max_tokens: int | None = None,
75
88
  tools: list[Tool] | None = None,
@@ -83,7 +96,7 @@ class BaseLLMClient(ABC, utils.InheritDecoratorsMixin):
83
96
  messages: list[Content],
84
97
  result_type: None = None,
85
98
  *,
86
- thinking_config: ThinkingConfig = ThinkingConfig(),
99
+ thinking_config: ThinkingConfig | None = None,
87
100
  system_message: str | None = None,
88
101
  max_tokens: int | None = None,
89
102
  tools: None = None,
@@ -95,7 +108,7 @@ class BaseLLMClient(ABC, utils.InheritDecoratorsMixin):
95
108
  messages: list[Content],
96
109
  result_type: Literal["json"],
97
110
  *,
98
- thinking_config: ThinkingConfig = ThinkingConfig(),
111
+ thinking_config: ThinkingConfig | None = None,
99
112
  system_message: str | None = None,
100
113
  max_tokens: int | None = None,
101
114
  tools: None = None,
@@ -107,7 +120,7 @@ class BaseLLMClient(ABC, utils.InheritDecoratorsMixin):
107
120
  messages: list[Content],
108
121
  result_type: type[PydanticStructure],
109
122
  *,
110
- thinking_config: ThinkingConfig = ThinkingConfig(),
123
+ thinking_config: ThinkingConfig | None = None,
111
124
  system_message: str | None = None,
112
125
  max_tokens: int | None = None,
113
126
  tools: None = None,
@@ -119,7 +132,7 @@ class BaseLLMClient(ABC, utils.InheritDecoratorsMixin):
119
132
  messages: list[Content],
120
133
  result_type: Literal["tools"],
121
134
  *,
122
- thinking_config: ThinkingConfig = ThinkingConfig(),
135
+ thinking_config: ThinkingConfig | None = None,
123
136
  system_message: str | None = None,
124
137
  max_tokens: int | None = None,
125
138
  tools: list[Tool],
@@ -131,12 +144,12 @@ class BaseLLMClient(ABC, utils.InheritDecoratorsMixin):
131
144
  messages: list[Content],
132
145
  result_type: ResultType | Literal["tools"] = None,
133
146
  *,
134
- thinking_config: ThinkingConfig = ThinkingConfig(),
147
+ thinking_config: ThinkingConfig | None = None,
135
148
  system_message: str | None = None,
136
149
  max_tokens: int | None = None,
137
150
  tools: list[Tool] | None = None,
138
151
  tool_choice_mode: Literal["ANY", "NONE"] = "NONE",
139
- autocomplete: bool = False
152
+ autocomplete: bool = False,
140
153
  ):
141
154
  if result_type == "tools":
142
155
  response = self.create(
@@ -220,7 +233,14 @@ class BaseLLMClient(ABC, utils.InheritDecoratorsMixin):
220
233
  @logfire_decorators.create_stream
221
234
  @utils.retry_cls
222
235
  @utils.rpm_limit_cls
223
- def create_stream(self, messages: list[Content], *, system_message: str | None = None, max_tokens: int | None = None) -> Iterator[Response]:
236
+ def create_stream(
237
+ self,
238
+ messages: list[Content],
239
+ *,
240
+ thinking_config: ThinkingConfig | None = None,
241
+ system_message: str | None = None,
242
+ max_tokens: int | None = None,
243
+ ) -> Iterator[Response]:
224
244
  raise NotImplementedError
225
245
 
226
246
  @overload
@@ -229,7 +249,7 @@ class BaseLLMClient(ABC, utils.InheritDecoratorsMixin):
229
249
  prompt: str,
230
250
  result_type: None = None,
231
251
  *,
232
- thinking_config: ThinkingConfig = ThinkingConfig(),
252
+ thinking_config: ThinkingConfig | None = None,
233
253
  system_message: str | None = None,
234
254
  max_tokens: int | None = None,
235
255
  tools: None = None,
@@ -241,7 +261,7 @@ class BaseLLMClient(ABC, utils.InheritDecoratorsMixin):
241
261
  prompt: str,
242
262
  result_type: Literal["json"],
243
263
  *,
244
- thinking_config: ThinkingConfig = ThinkingConfig(),
264
+ thinking_config: ThinkingConfig | None = None,
245
265
  system_message: str | None = None,
246
266
  max_tokens: int | None = None,
247
267
  tools: None = None,
@@ -253,7 +273,7 @@ class BaseLLMClient(ABC, utils.InheritDecoratorsMixin):
253
273
  prompt: str,
254
274
  result_type: type[PydanticStructure],
255
275
  *,
256
- thinking_config: ThinkingConfig = ThinkingConfig(),
276
+ thinking_config: ThinkingConfig | None = None,
257
277
  system_message: str | None = None,
258
278
  max_tokens: int | None = None,
259
279
  tools: None = None,
@@ -265,7 +285,7 @@ class BaseLLMClient(ABC, utils.InheritDecoratorsMixin):
265
285
  prompt: str,
266
286
  result_type: Literal["tools"],
267
287
  *,
268
- thinking_config: ThinkingConfig = ThinkingConfig(),
288
+ thinking_config: ThinkingConfig | None = None,
269
289
  system_message: str | None = None,
270
290
  max_tokens: int | None = None,
271
291
  tools: list[Tool],
@@ -277,7 +297,7 @@ class BaseLLMClient(ABC, utils.InheritDecoratorsMixin):
277
297
  prompt: str,
278
298
  result_type: ResultType | Literal["tools"] = None,
279
299
  *,
280
- thinking_config: ThinkingConfig = ThinkingConfig(),
300
+ thinking_config: ThinkingConfig | None = None,
281
301
  system_message: str | None = None,
282
302
  max_tokens: int | None = None,
283
303
  tools: list[Tool] | None = None,
@@ -297,7 +317,15 @@ class BaseLLMClient(ABC, utils.InheritDecoratorsMixin):
297
317
  class BaseLLMClientAsync(ABC, utils.InheritDecoratorsMixin):
298
318
  provider: str
299
319
 
300
- def __init__(self, provider: str, model: str, decorator_configs: utils.DecoratorConfigs | None = None, default_max_tokens: int | None = None, **kwargs):
320
+ def __init__(
321
+ self,
322
+ provider: str,
323
+ model: str,
324
+ decorator_configs: utils.DecoratorConfigs | None = None,
325
+ default_thinking_config: ThinkingConfig | None = None,
326
+ default_max_tokens: int | None = None,
327
+ **kwargs,
328
+ ):
301
329
  self.provider = provider
302
330
  self.model = model
303
331
 
@@ -308,6 +336,11 @@ class BaseLLMClientAsync(ABC, utils.InheritDecoratorsMixin):
308
336
  decorator_configs = utils.DecoratorConfigs()
309
337
  self._decorator_configs = decorator_configs
310
338
 
339
+ if default_thinking_config is None:
340
+ if self.full_model_name in GLOBAL_CONFIG.default_thinking_configs:
341
+ default_thinking_config = GLOBAL_CONFIG.default_thinking_configs[self.full_model_name]
342
+ self.default_thinking_config = default_thinking_config
343
+
311
344
  if default_max_tokens is None:
312
345
  if self.full_model_name in GLOBAL_CONFIG.default_max_tokens:
313
346
  default_max_tokens = GLOBAL_CONFIG.default_max_tokens[self.full_model_name]
@@ -332,7 +365,7 @@ class BaseLLMClientAsync(ABC, utils.InheritDecoratorsMixin):
332
365
  messages: list[Content],
333
366
  result_type: ResultType = None,
334
367
  *,
335
- thinking_config: ThinkingConfig = ThinkingConfig(),
368
+ thinking_config: ThinkingConfig | None = None,
336
369
  system_message: str | None = None,
337
370
  max_tokens: int | None = None,
338
371
  tools: list[Tool] | None = None,
@@ -346,7 +379,7 @@ class BaseLLMClientAsync(ABC, utils.InheritDecoratorsMixin):
346
379
  messages: list[Content],
347
380
  result_type: None = None,
348
381
  *,
349
- thinking_config: ThinkingConfig = ThinkingConfig(),
382
+ thinking_config: ThinkingConfig | None = None,
350
383
  system_message: str | None = None,
351
384
  max_tokens: int | None = None,
352
385
  tools: None = None,
@@ -358,7 +391,7 @@ class BaseLLMClientAsync(ABC, utils.InheritDecoratorsMixin):
358
391
  messages: list[Content],
359
392
  result_type: Literal["json"],
360
393
  *,
361
- thinking_config: ThinkingConfig = ThinkingConfig(),
394
+ thinking_config: ThinkingConfig | None = None,
362
395
  system_message: str | None = None,
363
396
  max_tokens: int | None = None,
364
397
  tools: None = None,
@@ -370,7 +403,7 @@ class BaseLLMClientAsync(ABC, utils.InheritDecoratorsMixin):
370
403
  messages: list[Content],
371
404
  result_type: type[PydanticStructure],
372
405
  *,
373
- thinking_config: ThinkingConfig = ThinkingConfig(),
406
+ thinking_config: ThinkingConfig | None = None,
374
407
  system_message: str | None = None,
375
408
  max_tokens: int | None = None,
376
409
  tools: None = None,
@@ -382,7 +415,7 @@ class BaseLLMClientAsync(ABC, utils.InheritDecoratorsMixin):
382
415
  messages: list[Content],
383
416
  result_type: Literal["tools"],
384
417
  *,
385
- thinking_config: ThinkingConfig = ThinkingConfig(),
418
+ thinking_config: ThinkingConfig | None = None,
386
419
  system_message: str | None = None,
387
420
  max_tokens: int | None = None,
388
421
  tools: list[Tool],
@@ -394,12 +427,12 @@ class BaseLLMClientAsync(ABC, utils.InheritDecoratorsMixin):
394
427
  messages: list[Content],
395
428
  result_type: ResultType | Literal["tools"] = None,
396
429
  *,
397
- thinking_config: ThinkingConfig = ThinkingConfig(),
430
+ thinking_config: ThinkingConfig | None = None,
398
431
  system_message: str | None = None,
399
432
  max_tokens: int | None = None,
400
433
  tools: list[Tool] | None = None,
401
434
  tool_choice_mode: Literal["ANY", "NONE"] = "NONE",
402
- autocomplete: bool = False
435
+ autocomplete: bool = False,
403
436
  ):
404
437
  if result_type == "tools":
405
438
  response = await self.create(
@@ -454,7 +487,14 @@ class BaseLLMClientAsync(ABC, utils.InheritDecoratorsMixin):
454
487
  @logfire_decorators.create_stream_async
455
488
  @utils.retry_cls_async
456
489
  @utils.rpm_limit_cls_async
457
- async def create_stream(self, messages: list[Content], *, system_message: str | None = None, max_tokens: int | None = None) -> AsyncIterator[Response]:
490
+ async def create_stream(
491
+ self,
492
+ messages: list[Content],
493
+ *,
494
+ thinking_config: ThinkingConfig | None = None,
495
+ system_message: str | None = None,
496
+ max_tokens: int | None = None,
497
+ ) -> AsyncIterator[Response]:
458
498
  raise NotImplementedError
459
499
 
460
500
  @overload
@@ -463,7 +503,7 @@ class BaseLLMClientAsync(ABC, utils.InheritDecoratorsMixin):
463
503
  prompt: str,
464
504
  result_type: None = None,
465
505
  *,
466
- thinking_config: ThinkingConfig = ThinkingConfig(),
506
+ thinking_config: ThinkingConfig | None = None,
467
507
  system_message: str | None = None,
468
508
  max_tokens: int | None = None,
469
509
  tools: None = None,
@@ -475,7 +515,7 @@ class BaseLLMClientAsync(ABC, utils.InheritDecoratorsMixin):
475
515
  prompt: str,
476
516
  result_type: Literal["json"],
477
517
  *,
478
- thinking_config: ThinkingConfig = ThinkingConfig(),
518
+ thinking_config: ThinkingConfig | None = None,
479
519
  system_message: str | None = None,
480
520
  max_tokens: int | None = None,
481
521
  tools: None = None,
@@ -487,7 +527,7 @@ class BaseLLMClientAsync(ABC, utils.InheritDecoratorsMixin):
487
527
  prompt: str,
488
528
  result_type: type[PydanticStructure],
489
529
  *,
490
- thinking_config: ThinkingConfig = ThinkingConfig(),
530
+ thinking_config: ThinkingConfig | None = None,
491
531
  system_message: str | None = None,
492
532
  max_tokens: int | None = None,
493
533
  tools: None = None,
@@ -499,7 +539,7 @@ class BaseLLMClientAsync(ABC, utils.InheritDecoratorsMixin):
499
539
  prompt: str,
500
540
  result_type: Literal["tools"],
501
541
  *,
502
- thinking_config: ThinkingConfig = ThinkingConfig(),
542
+ thinking_config: ThinkingConfig | None = None,
503
543
  system_message: str | None = None,
504
544
  max_tokens: int | None = None,
505
545
  tools: list[Tool],
@@ -511,7 +551,7 @@ class BaseLLMClientAsync(ABC, utils.InheritDecoratorsMixin):
511
551
  prompt: str,
512
552
  result_type: ResultType | Literal["tools"] = None,
513
553
  *,
514
- thinking_config: ThinkingConfig = ThinkingConfig(),
554
+ thinking_config: ThinkingConfig | None = None,
515
555
  system_message: str | None = None,
516
556
  max_tokens: int | None = None,
517
557
  tools: list[Tool] | None = None,
@@ -534,7 +574,13 @@ class CachedLLMClient(BaseLLMClient):
534
574
  return self.llm_client.api_key
535
575
 
536
576
  def __init__(self, llm_client: BaseLLMClient, cache_dir: str = "data/llm_cache"):
537
- super().__init__(provider=llm_client.provider, model=llm_client.model, decorator_configs=llm_client._decorator_configs, default_max_tokens=llm_client.default_max_tokens)
577
+ super().__init__(
578
+ provider=llm_client.provider,
579
+ model=llm_client.model,
580
+ decorator_configs=llm_client._decorator_configs,
581
+ default_thinking_config=llm_client.default_thinking_config,
582
+ default_max_tokens=llm_client.default_max_tokens,
583
+ )
538
584
  self.provider = llm_client.provider
539
585
  self.llm_client = llm_client
540
586
  self.cache_dir = cache_dir
@@ -53,6 +53,7 @@ class BedrockLLMClient(BaseLLMClient):
53
53
  model: str,
54
54
  api_key: BedrockApiKey = BedrockApiKey(),
55
55
  decorator_configs: DecoratorConfigs | None = None,
56
+ default_thinking_config: ThinkingConfig | None = None,
56
57
  default_max_tokens: int | None = None,
57
58
  **kwargs,
58
59
  ):
@@ -61,7 +62,7 @@ class BedrockLLMClient(BaseLLMClient):
61
62
  "To create a bedrock llm client you need to either set the environment variables "
62
63
  "AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and optional AWS_DEFAULT_REGION or pass the api_key as BedrockApiKey instance"
63
64
  )
64
- super().__init__(BedrockLLMClient.PROVIDER, model, decorator_configs=decorator_configs, default_max_tokens=default_max_tokens)
65
+ super().__init__(BedrockLLMClient.PROVIDER, model, decorator_configs=decorator_configs, default_thinking_config=default_thinking_config, default_max_tokens=default_max_tokens)
65
66
  self._api_key = api_key
66
67
 
67
68
  @property
@@ -73,7 +74,7 @@ class BedrockLLMClient(BaseLLMClient):
73
74
  messages: list[Content],
74
75
  result_type: ResultType = None,
75
76
  *,
76
- thinking_config: ThinkingConfig = ThinkingConfig(),
77
+ thinking_config: ThinkingConfig | None = None,
77
78
  system_message: str | None = None,
78
79
  max_tokens: int | None = None,
79
80
  tools: list[Tool] | None = None,
@@ -230,6 +231,7 @@ class BedrockLLMClient(BaseLLMClient):
230
231
  self,
231
232
  messages: list[Content],
232
233
  *,
234
+ thinking_config: ThinkingConfig | None = None,
233
235
  system_message: str | None = None,
234
236
  max_tokens: int | None = None,
235
237
  ) -> Iterator[Response]:
@@ -313,6 +315,7 @@ class BedrockLLMClientAsync(BaseLLMClientAsync):
313
315
  model: str,
314
316
  api_key: BedrockApiKey = BedrockApiKey(),
315
317
  decorator_configs: DecoratorConfigs | None = None,
318
+ default_thinking_config: ThinkingConfig | None = None,
316
319
  default_max_tokens: int | None = None,
317
320
  **kwargs,
318
321
  ):
@@ -321,7 +324,7 @@ class BedrockLLMClientAsync(BaseLLMClientAsync):
321
324
  "To create a bedrock llm client you need to either set the environment variables "
322
325
  "AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and optional AWS_DEFAULT_REGION or pass the api_key as BedrockApiKey instance"
323
326
  )
324
- super().__init__(BedrockLLMClient.PROVIDER, model, decorator_configs=decorator_configs, default_max_tokens=default_max_tokens)
327
+ super().__init__(BedrockLLMClient.PROVIDER, model, decorator_configs=decorator_configs, default_thinking_config=default_thinking_config, default_max_tokens=default_max_tokens)
325
328
  self._api_key = api_key
326
329
  self._aioboto_session = aioboto3.Session(
327
330
  aws_access_key_id=api_key.aws_access_key_id,
@@ -338,7 +341,7 @@ class BedrockLLMClientAsync(BaseLLMClientAsync):
338
341
  messages: list[Content],
339
342
  result_type: ResultType = None,
340
343
  *,
341
- thinking_config: ThinkingConfig = ThinkingConfig(),
344
+ thinking_config: ThinkingConfig | None = None,
342
345
  system_message: str | None = None,
343
346
  max_tokens: int | None = None,
344
347
  tools: list[Tool] | None = None,
@@ -489,6 +492,7 @@ class BedrockLLMClientAsync(BaseLLMClientAsync):
489
492
  self,
490
493
  messages: list[Content],
491
494
  *,
495
+ thinking_config: ThinkingConfig | None = None,
492
496
  system_message: str | None = None,
493
497
  max_tokens: int | None = None,
494
498
  ) -> AsyncIterator[Response]:
@@ -1,6 +1,7 @@
1
1
  import dataclasses
2
2
 
3
3
  from promptbuilder.llm_client.utils import DecoratorConfigs
4
+ from promptbuilder.llm_client.types import ThinkingConfig
4
5
 
5
6
 
6
7
  @dataclasses.dataclass
@@ -9,6 +10,9 @@ class LlmClientConfigs:
9
10
  default_decorator_configs: dict[str, DecoratorConfigs] = dataclasses.field(default_factory=dict)
10
11
  """Dictionary mapping a client name to the default decorator configs to be used for that model."""
11
12
 
13
+ default_thinking_configs: dict[str, ThinkingConfig] = dataclasses.field(default_factory=dict)
14
+ """Dictionary mapping a client name to the default thinking config to be used for that model."""
15
+
12
16
  default_max_tokens: dict[str, int] = dataclasses.field(default_factory=dict)
13
17
  """Dictionary mapping a client name to the default max_tokens value to be used for that model."""
14
18
 
@@ -17,12 +17,13 @@ class GoogleLLMClient(BaseLLMClient):
17
17
  model: str,
18
18
  api_key: str = os.getenv("GOOGLE_API_KEY"),
19
19
  decorator_configs: DecoratorConfigs | None = None,
20
+ default_thinking_config: ThinkingConfig | None = None,
20
21
  default_max_tokens: int | None = None,
21
22
  **kwargs,
22
23
  ):
23
24
  if api_key is None or not isinstance(api_key, str):
24
25
  raise ValueError("To create a google llm client you need to either set the environment variable GOOGLE_API_KEY or pass the api_key in string format")
25
- super().__init__(GoogleLLMClient.PROVIDER, model, decorator_configs=decorator_configs, default_max_tokens=default_max_tokens)
26
+ super().__init__(GoogleLLMClient.PROVIDER, model, decorator_configs=decorator_configs, default_thinking_config=default_thinking_config, default_max_tokens=default_max_tokens)
26
27
  self._api_key = api_key
27
28
  self.client = Client(api_key=api_key)
28
29
 
@@ -58,7 +59,7 @@ class GoogleLLMClient(BaseLLMClient):
58
59
  messages: list[Content],
59
60
  result_type: ResultType = None,
60
61
  *,
61
- thinking_config: ThinkingConfig = ThinkingConfig(),
62
+ thinking_config: ThinkingConfig | None = None,
62
63
  system_message: str | None = None,
63
64
  max_tokens: int | None = None,
64
65
  tools: list[Tool] | None = None,
@@ -74,10 +75,9 @@ class GoogleLLMClient(BaseLLMClient):
74
75
  tool_config=tool_config,
75
76
  )
76
77
 
77
- if not thinking_config.include_thoughts:
78
- thinking_config = ThinkingConfig(include_thoughts=False, thinking_budget=0)
79
- if thinking_config.include_thoughts or "gemini-2.5-pro-preview-05-06" in self.model:
80
- config.thinking_config = thinking_config
78
+ if thinking_config is None:
79
+ thinking_config = self.default_thinking_config
80
+ config.thinking_config = thinking_config
81
81
 
82
82
  if result_type is None:
83
83
  return self.client.models.generate_content(
@@ -108,6 +108,7 @@ class GoogleLLMClient(BaseLLMClient):
108
108
  self,
109
109
  messages: list[Content],
110
110
  *,
111
+ thinking_config: ThinkingConfig | None = None,
111
112
  system_message: str | None = None,
112
113
  max_tokens: int | None = None,
113
114
  ) -> Iterator[Response]:
@@ -116,8 +117,12 @@ class GoogleLLMClient(BaseLLMClient):
116
117
  config = types.GenerateContentConfig(
117
118
  system_instruction=system_message,
118
119
  max_output_tokens=max_tokens,
119
- thinking_config=ThinkingConfig(include_thoughts=False, thinking_budget=0),
120
120
  )
121
+
122
+ if thinking_config is None:
123
+ thinking_config = self.default_thinking_config
124
+ config.thinking_config = thinking_config
125
+
121
126
  response = self.client.models.generate_content_stream(
122
127
  model=self.model,
123
128
  contents=messages,
@@ -162,12 +167,13 @@ class GoogleLLMClientAsync(BaseLLMClientAsync):
162
167
  model: str,
163
168
  api_key: str = os.getenv("GOOGLE_API_KEY"),
164
169
  decorator_configs: DecoratorConfigs | None = None,
170
+ default_thinking_config: ThinkingConfig | None = None,
165
171
  default_max_tokens: int | None = None,
166
172
  **kwargs,
167
173
  ):
168
174
  if api_key is None or not isinstance(api_key, str):
169
175
  raise ValueError("To create a google llm client you need to either set the environment variable GOOGLE_API_KEY or pass the api_key in string format")
170
- super().__init__(GoogleLLMClientAsync.PROVIDER, model, decorator_configs=decorator_configs, default_max_tokens=default_max_tokens)
176
+ super().__init__(GoogleLLMClientAsync.PROVIDER, model, decorator_configs=decorator_configs, default_thinking_config=default_thinking_config, default_max_tokens=default_max_tokens)
171
177
  self._api_key = api_key
172
178
  self.client = Client(api_key=api_key)
173
179
 
@@ -180,7 +186,7 @@ class GoogleLLMClientAsync(BaseLLMClientAsync):
180
186
  messages: list[Content],
181
187
  result_type: ResultType = None,
182
188
  *,
183
- thinking_config: ThinkingConfig = ThinkingConfig(),
189
+ thinking_config: ThinkingConfig | None = None,
184
190
  system_message: str | None = None,
185
191
  max_tokens: int | None = None,
186
192
  tools: list[Tool] | None = None,
@@ -196,10 +202,9 @@ class GoogleLLMClientAsync(BaseLLMClientAsync):
196
202
  tool_config=tool_config,
197
203
  )
198
204
 
199
- if not thinking_config.include_thoughts:
200
- thinking_config = ThinkingConfig(include_thoughts=False, thinking_budget=0)
201
- if thinking_config.include_thoughts or "gemini-2.5" in self.model:
202
- config.thinking_config = thinking_config
205
+ if thinking_config is None:
206
+ thinking_config = self.default_thinking_config
207
+ config.thinking_config = thinking_config
203
208
 
204
209
  if result_type is None or result_type == "json":
205
210
  return await self.client.aio.models.generate_content(
@@ -222,6 +227,7 @@ class GoogleLLMClientAsync(BaseLLMClientAsync):
222
227
  self,
223
228
  messages: list[Content],
224
229
  *,
230
+ thinking_config: ThinkingConfig | None = None,
225
231
  system_message: str | None = None,
226
232
  max_tokens: int | None = None,
227
233
  ) -> AsyncIterator[Response]:
@@ -230,8 +236,12 @@ class GoogleLLMClientAsync(BaseLLMClientAsync):
230
236
  config = types.GenerateContentConfig(
231
237
  system_instruction=system_message,
232
238
  max_output_tokens=max_tokens,
233
- thinking_config=ThinkingConfig(include_thoughts=False, thinking_budget=0),
234
239
  )
240
+
241
+ if thinking_config is None:
242
+ thinking_config = self.default_thinking_config
243
+ config.thinking_config = thinking_config
244
+
235
245
  response = await self.client.aio.models.generate_content_stream(
236
246
  model=self.model,
237
247
  contents=messages,
@@ -1,7 +1,7 @@
1
1
  import warnings
2
2
  from itertools import chain
3
3
 
4
- from promptbuilder.llm_client.types import ApiKey, Model
4
+ from promptbuilder.llm_client.types import ApiKey, Model, ThinkingConfig
5
5
  from promptbuilder.llm_client.base_client import BaseLLMClient, BaseLLMClientAsync
6
6
  from promptbuilder.llm_client.config import GLOBAL_CONFIG
7
7
  from promptbuilder.llm_client.utils import DecoratorConfigs
@@ -17,41 +17,45 @@ _memory: dict[tuple[str, ApiKey], BaseLLMClient] = {}
17
17
  _memory_async: dict[tuple[str, ApiKey], BaseLLMClientAsync] = {}
18
18
 
19
19
 
20
- def get_client(full_model_name: str, api_key: ApiKey | None = None, decorator_configs: DecoratorConfigs | None = None, default_max_tokens: int | None = None) -> BaseLLMClient:
20
+ def get_client(
21
+ full_model_name: str,
22
+ api_key: ApiKey | None = None,
23
+ decorator_configs: DecoratorConfigs | None = None,
24
+ default_thinking_config: ThinkingConfig | None = None,
25
+ default_max_tokens: int | None = None,
26
+ ) -> BaseLLMClient:
21
27
  global _memory
22
28
 
29
+ kwargs = {
30
+ "decorator_configs": decorator_configs,
31
+ "default_thinking_config": default_thinking_config,
32
+ "default_max_tokens": default_max_tokens,
33
+ }
34
+ provider_to_client_class: dict[str, type[BaseLLMClient]] = {
35
+ "google": GoogleLLMClient,
36
+ "anthropic": AnthropicLLMClient,
37
+ "openai": OpenaiLLMClient,
38
+ "bedrock": BedrockLLMClient,
39
+ }
23
40
  provider, model = full_model_name.split(":", 1)
24
- match provider:
25
- case "google":
26
- if api_key is None:
27
- client = GoogleLLMClient(model, decorator_configs=decorator_configs, default_max_tokens=default_max_tokens)
28
- else:
29
- client = GoogleLLMClient(model, api_key, decorator_configs=decorator_configs, default_max_tokens=default_max_tokens)
30
- case "anthropic":
31
- if api_key is None:
32
- client = AnthropicLLMClient(model, decorator_configs=decorator_configs, default_max_tokens=default_max_tokens)
33
- else:
34
- client = AnthropicLLMClient(model, api_key, decorator_configs=decorator_configs, default_max_tokens=default_max_tokens)
35
- case "openai":
36
- if api_key is None:
37
- client = OpenaiLLMClient(model, decorator_configs=decorator_configs, default_max_tokens=default_max_tokens)
38
- else:
39
- client = OpenaiLLMClient(model, api_key, decorator_configs=decorator_configs, default_max_tokens=default_max_tokens)
40
- case "bedrock":
41
- if api_key is None:
42
- client = BedrockLLMClient(model, decorator_configs=decorator_configs, default_max_tokens=default_max_tokens)
43
- else:
44
- client = BedrockLLMClient(model, api_key, decorator_configs=decorator_configs, default_max_tokens=default_max_tokens)
45
- case _:
46
- if api_key is None:
47
- raise ValueError(f"You should directly provide api_key for this provider: {provider}")
48
- else:
49
- client = AiSuiteLLMClient(full_model_name, api_key, decorator_configs=decorator_configs, default_max_tokens=default_max_tokens)
41
+ if provider in provider_to_client_class:
42
+ client_class = provider_to_client_class[provider]
43
+ if api_key is None:
44
+ client = client_class(model, **kwargs)
45
+ else:
46
+ client = client_class(model, api_key, **kwargs)
47
+ else:
48
+ if api_key is None:
49
+ raise ValueError(f"You should directly provide api_key for this provider: {provider}")
50
+ else:
51
+ client = AiSuiteLLMClient(full_model_name, api_key, **kwargs)
50
52
 
51
53
  if (full_model_name, client.api_key) in _memory:
52
54
  client = _memory[(full_model_name, client.api_key)]
53
55
  if decorator_configs is not None:
54
56
  client._decorator_configs = decorator_configs
57
+ if default_thinking_config is not None:
58
+ client.default_thinking_config = default_thinking_config
55
59
  if default_max_tokens is not None:
56
60
  client.default_max_tokens = default_max_tokens
57
61
  return client
@@ -60,42 +64,45 @@ def get_client(full_model_name: str, api_key: ApiKey | None = None, decorator_co
60
64
  return client
61
65
 
62
66
 
63
- def get_async_client(full_model_name: str, api_key: ApiKey | None = None, decorator_configs: DecoratorConfigs | None = None, default_max_tokens: int | None = None) -> BaseLLMClientAsync:
67
+ def get_async_client(
68
+ full_model_name: str,
69
+ api_key: ApiKey | None = None,
70
+ decorator_configs: DecoratorConfigs | None = None,
71
+ default_thinking_config: ThinkingConfig | None = None,
72
+ default_max_tokens: int | None = None,
73
+ ) -> BaseLLMClientAsync:
64
74
  global _memory_async
65
75
 
66
-
76
+ kwargs = {
77
+ "decorator_configs": decorator_configs,
78
+ "default_thinking_config": default_thinking_config,
79
+ "default_max_tokens": default_max_tokens,
80
+ }
81
+ provider_to_client_class: dict[str, type[BaseLLMClientAsync]] = {
82
+ "google": GoogleLLMClientAsync,
83
+ "anthropic": AnthropicLLMClientAsync,
84
+ "openai": OpenaiLLMClientAsync,
85
+ "bedrock": BedrockLLMClientAsync,
86
+ }
67
87
  provider, model = full_model_name.split(":", 1)
68
- match provider:
69
- case "google":
70
- if api_key is None:
71
- client = GoogleLLMClientAsync(model, decorator_configs=decorator_configs, default_max_tokens=default_max_tokens)
72
- else:
73
- client = GoogleLLMClientAsync(model, api_key, decorator_configs=decorator_configs, default_max_tokens=default_max_tokens)
74
- case "anthropic":
75
- if api_key is None:
76
- client = AnthropicLLMClientAsync(model, decorator_configs=decorator_configs, default_max_tokens=default_max_tokens)
77
- else:
78
- client = AnthropicLLMClientAsync(model, api_key, decorator_configs=decorator_configs, default_max_tokens=default_max_tokens)
79
- case "openai":
80
- if api_key is None:
81
- client = OpenaiLLMClientAsync(model, decorator_configs=decorator_configs, default_max_tokens=default_max_tokens)
82
- else:
83
- client = OpenaiLLMClientAsync(model, api_key, decorator_configs=decorator_configs, default_max_tokens=default_max_tokens)
84
- case "bedrock":
85
- if api_key is None:
86
- client = BedrockLLMClientAsync(model, decorator_configs=decorator_configs, default_max_tokens=default_max_tokens)
87
- else:
88
- client = BedrockLLMClientAsync(model, api_key, decorator_configs=decorator_configs, default_max_tokens=default_max_tokens)
89
- case _:
90
- if api_key is None:
91
- raise ValueError(f"You should directly provide api_key for this provider: {provider}")
92
- else:
93
- client = AiSuiteLLMClientAsync(full_model_name, api_key, decorator_configs=decorator_configs, default_max_tokens=default_max_tokens)
88
+ if provider in provider_to_client_class:
89
+ client_class = provider_to_client_class[provider]
90
+ if api_key is None:
91
+ client = client_class(model, **kwargs)
92
+ else:
93
+ client = client_class(model, api_key, **kwargs)
94
+ else:
95
+ if api_key is None:
96
+ raise ValueError(f"You should directly provide api_key for this provider: {provider}")
97
+ else:
98
+ client = AiSuiteLLMClientAsync(full_model_name, api_key, **kwargs)
94
99
 
95
100
  if (full_model_name, client.api_key) in _memory_async:
96
101
  client = _memory_async[(full_model_name, client.api_key)]
97
102
  if decorator_configs is not None:
98
103
  client._decorator_configs = decorator_configs
104
+ if default_thinking_config is not None:
105
+ client.default_thinking_config = default_thinking_config
99
106
  if default_max_tokens is not None:
100
107
  client.default_max_tokens = default_max_tokens
101
108
  return client
@@ -130,6 +137,8 @@ def configure(
130
137
  *,
131
138
  decorator_configs: dict[str, DecoratorConfigs] | None = None,
132
139
  update_decorator_configs: dict[str, DecoratorConfigs] | None = None,
140
+ thinking_configs: dict[str, ThinkingConfig] | None = None,
141
+ update_thinking_configs: dict[str, ThinkingConfig] | None = None,
133
142
  max_tokens: dict[str, int] | None = None,
134
143
  update_max_tokens: dict[str, int] | None = None,
135
144
  use_logfire: bool | None = None,
@@ -138,6 +147,10 @@ def configure(
138
147
  warnings.warn("Both 'decorator_configs' and 'update_decorator_configs' were provided. "
139
148
  "'update_decorator_configs' will be ignored.", UserWarning)
140
149
  update_decorator_configs = None
150
+ if thinking_configs is not None and update_thinking_configs is not None:
151
+ warnings.warn("Both 'thinking_configs' and 'update_thinking_configs' were provided. "
152
+ "'update_thinking_configs' will be ignored.", UserWarning)
153
+ update_thinking_configs = None
141
154
  if max_tokens is not None and update_max_tokens is not None:
142
155
  warnings.warn("Both 'max_tokens' and 'update_max_tokens' were provided. "
143
156
  "'update_max_tokens' will be ignored.", UserWarning)
@@ -148,6 +161,11 @@ def configure(
148
161
  if update_decorator_configs is not None:
149
162
  GLOBAL_CONFIG.default_decorator_configs.update(update_decorator_configs)
150
163
 
164
+ if thinking_configs is not None:
165
+ GLOBAL_CONFIG.default_thinking_configs = thinking_configs
166
+ if update_thinking_configs is not None:
167
+ GLOBAL_CONFIG.default_thinking_configs.update(update_thinking_configs)
168
+
151
169
  if max_tokens is not None:
152
170
  GLOBAL_CONFIG.default_max_tokens = max_tokens
153
171
  if update_max_tokens is not None:
@@ -163,6 +181,11 @@ def sync_existing_clients_with_global_config():
163
181
  else:
164
182
  llm_client._decorator_configs = DecoratorConfigs()
165
183
 
184
+ if full_model_name in GLOBAL_CONFIG.default_thinking_configs:
185
+ llm_client.default_thinking_config = GLOBAL_CONFIG.default_thinking_configs[full_model_name]
186
+ else:
187
+ llm_client.default_thinking_config = None
188
+
166
189
  if full_model_name in GLOBAL_CONFIG.default_max_tokens:
167
190
  llm_client.default_max_tokens = GLOBAL_CONFIG.default_max_tokens[full_model_name]
168
191
  else:
@@ -45,12 +45,13 @@ class OpenaiLLMClient(BaseLLMClient):
45
45
  model: str,
46
46
  api_key: str = os.getenv("OPENAI_API_KEY"),
47
47
  decorator_configs: DecoratorConfigs | None = None,
48
+ default_thinking_config: ThinkingConfig | None = None,
48
49
  default_max_tokens: int | None = None,
49
50
  **kwargs,
50
51
  ):
51
52
  if api_key is None or not isinstance(api_key, str):
52
53
  raise ValueError("To create an openai llm client you need to either set the environment variable OPENAI_API_KEY or pass the api_key in string format")
53
- super().__init__(OpenaiLLMClient.PROVIDER, model, decorator_configs=decorator_configs, default_max_tokens=default_max_tokens)
54
+ super().__init__(OpenaiLLMClient.PROVIDER, model, decorator_configs=decorator_configs, default_thinking_config=default_thinking_config, default_max_tokens=default_max_tokens)
54
55
  self._api_key = api_key
55
56
  self.client = OpenAI(api_key=api_key)
56
57
 
@@ -92,7 +93,10 @@ class OpenaiLLMClient(BaseLLMClient):
92
93
  return openai_messages
93
94
 
94
95
  @staticmethod
95
- def _process_thinking_config(thinking_config: ThinkingConfig) -> dict[str, str]:
96
+ def _process_thinking_config(thinking_config: ThinkingConfig | None) -> dict[str, str]:
97
+ if thinking_config is None:
98
+ return {}
99
+
96
100
  openai_thinking_config = {}
97
101
  if thinking_config.include_thoughts:
98
102
  # openai_thinking_config["summary"] = "auto"
@@ -114,7 +118,7 @@ class OpenaiLLMClient(BaseLLMClient):
114
118
  messages: list[Content],
115
119
  result_type: ResultType = None,
116
120
  *,
117
- thinking_config: ThinkingConfig = ThinkingConfig(),
121
+ thinking_config: ThinkingConfig | None = None,
118
122
  system_message: str | None = None,
119
123
  max_tokens: int | None = None,
120
124
  tools: list[Tool] | None = None,
@@ -131,6 +135,8 @@ class OpenaiLLMClient(BaseLLMClient):
131
135
  "input": openai_messages,
132
136
  }
133
137
 
138
+ if thinking_config is None:
139
+ thinking_config = self.default_thinking_config
134
140
  openai_kwargs.update(OpenaiLLMClient._process_thinking_config(thinking_config))
135
141
 
136
142
  if tools is not None:
@@ -222,6 +228,7 @@ class OpenaiLLMClient(BaseLLMClient):
222
228
  self,
223
229
  messages: list[Content],
224
230
  *,
231
+ thinking_config: ThinkingConfig | None = None,
225
232
  system_message: str | None = None,
226
233
  max_tokens: int | None = None,
227
234
  ) -> Iterator[Response]:
@@ -235,6 +242,11 @@ class OpenaiLLMClient(BaseLLMClient):
235
242
  "max_output_tokens": max_tokens,
236
243
  "input": openai_messages,
237
244
  }
245
+
246
+ if thinking_config is None:
247
+ thinking_config = self.default_thinking_config
248
+ openai_kwargs.update(OpenaiLLMClient._process_thinking_config(thinking_config))
249
+
238
250
  response = self.client.responses.create(**openai_kwargs, stream=True)
239
251
  return OpenaiStreamIterator(response)
240
252
 
@@ -298,12 +310,13 @@ class OpenaiLLMClientAsync(BaseLLMClientAsync):
298
310
  model: str,
299
311
  api_key: str = os.getenv("OPENAI_API_KEY"),
300
312
  decorator_configs: DecoratorConfigs | None = None,
313
+ default_thinking_config: ThinkingConfig | None = None,
301
314
  default_max_tokens: int | None = None,
302
315
  **kwargs,
303
316
  ):
304
317
  if api_key is None or not isinstance(api_key, str):
305
318
  raise ValueError("To create an openai llm client you need to either set the environment variable OPENAI_API_KEY or pass the api_key in string format")
306
- super().__init__(OpenaiLLMClientAsync.PROVIDER, model, decorator_configs=decorator_configs, default_max_tokens=default_max_tokens)
319
+ super().__init__(OpenaiLLMClientAsync.PROVIDER, model, decorator_configs=decorator_configs, default_thinking_config=default_thinking_config, default_max_tokens=default_max_tokens)
307
320
  self._api_key = api_key
308
321
  self.client = AsyncOpenAI(api_key=api_key)
309
322
 
@@ -315,7 +328,8 @@ class OpenaiLLMClientAsync(BaseLLMClientAsync):
315
328
  self,
316
329
  messages: list[Content],
317
330
  result_type: ResultType = None,
318
- thinking_config: ThinkingConfig = ThinkingConfig(),
331
+ *,
332
+ thinking_config: ThinkingConfig | None = None,
319
333
  system_message: str | None = None,
320
334
  max_tokens: int | None = None,
321
335
  tools: list[Tool] | None = None,
@@ -339,6 +353,8 @@ class OpenaiLLMClientAsync(BaseLLMClientAsync):
339
353
  "input": openai_messages,
340
354
  }
341
355
 
356
+ if thinking_config is None:
357
+ thinking_config = self.default_thinking_config
342
358
  openai_kwargs.update(OpenaiLLMClient._process_thinking_config(thinking_config))
343
359
 
344
360
  if tools is not None:
@@ -430,6 +446,7 @@ class OpenaiLLMClientAsync(BaseLLMClientAsync):
430
446
  self,
431
447
  messages: list[Content],
432
448
  *,
449
+ thinking_config: ThinkingConfig | None = None,
433
450
  system_message: str | None = None,
434
451
  max_tokens: int | None = None,
435
452
  ) -> AsyncIterator[Response]:
@@ -450,6 +467,11 @@ class OpenaiLLMClientAsync(BaseLLMClientAsync):
450
467
  "max_output_tokens": max_tokens,
451
468
  "input": openai_messages,
452
469
  }
470
+
471
+ if thinking_config is None:
472
+ thinking_config = self.default_thinking_config
473
+ openai_kwargs.update(OpenaiLLMClient._process_thinking_config(thinking_config))
474
+
453
475
  response = await self.client.responses.create(**openai_kwargs, stream=True)
454
476
  return OpenaiStreamIteratorAsync(response)
455
477
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: promptbuilder
3
- Version: 0.4.17
3
+ Version: 0.4.18
4
4
  Summary: Library for building prompts for LLMs
5
5
  Home-page: https://github.com/kapulkin/promptbuilder
6
6
  Author: Kapulkin Stanislav
@@ -14,7 +14,7 @@ License-File: LICENSE
14
14
  Requires-Dist: pydantic
15
15
  Requires-Dist: pytest
16
16
  Requires-Dist: aisuite-async
17
- Requires-Dist: google-genai
17
+ Requires-Dist: google-genai<=1.21.0,>=1.4.0
18
18
  Requires-Dist: anthropic
19
19
  Requires-Dist: openai
20
20
  Requires-Dist: aioboto3
@@ -7,18 +7,18 @@ promptbuilder/agent/tool.py,sha256=VDbIHK3_Q62Ei7hwLF7nIgHq-PTMKnv1NSjHpDYkUZE,2
7
7
  promptbuilder/agent/utils.py,sha256=vTkphKw04v_QDIJtoB2JKK0RGY6iI1t_0LbmuStunzI,356
8
8
  promptbuilder/llm_client/__init__.py,sha256=2tPVYqwNdwTRdIg4Pde6Nc259FJvy70gjEj1N2oqNrc,458
9
9
  promptbuilder/llm_client/aisuite_client.py,sha256=aMqg05zefzck9Lz7pm7jZoKFdzr_ymFYhrAjZtzdHlQ,15561
10
- promptbuilder/llm_client/anthropic_client.py,sha256=q0IP_MK1Nb94CU28bDBpnIreOoTTLcJqNRsSj-SMNsw,24454
11
- promptbuilder/llm_client/base_client.py,sha256=7KwjTA43JF3DriIO9_uONg2klX4l3qplCUhosP6tfnk,23114
12
- promptbuilder/llm_client/bedrock_client.py,sha256=nbyHQxLKl1nONNSnQtF9euj2kwBJb147fQetjU17Z38,25444
13
- promptbuilder/llm_client/config.py,sha256=Qgk9XeBGJdElY6cx91yz_e7eZJ_Ced6vAI9ByV_6lIA,858
14
- promptbuilder/llm_client/google_client.py,sha256=3w7g38r2NAP780nLZxegc3qQkIWEVUTRuQH6VvtKAEg,9606
10
+ promptbuilder/llm_client/anthropic_client.py,sha256=JeTVC26ahuJJT4G_3Bsoc4TqLzVDPuJpJiCRxTALnqA,26146
11
+ promptbuilder/llm_client/base_client.py,sha256=GS-Qb20WtZnljmEUD2ibhTHDet7exoyhQ0_mGNAEKlg,24219
12
+ promptbuilder/llm_client/bedrock_client.py,sha256=W4wFW7Vbv-nsT2ReyhJ4YIPSTXxE_4S83352vJDSmDk,25772
13
+ promptbuilder/llm_client/config.py,sha256=exQEm35wp7lK5SfXNpN5H9VZEb2LVa4pyZ-cxGt1U-U,1124
14
+ promptbuilder/llm_client/google_client.py,sha256=heyeACt_0bVP3p4pCQeWR92MhCsyNk844kWJ_0MVTfg,9830
15
15
  promptbuilder/llm_client/logfire_decorators.py,sha256=un_QnIekypOEcqTZ5v1y9pwijGnF95xwnwKO5rFSHVY,9667
16
- promptbuilder/llm_client/main.py,sha256=-naNScxlU-guvoPYJpThYNupGkl-ZQoViCGExDIR1gA,8566
17
- promptbuilder/llm_client/openai_client.py,sha256=X7UWLaiAkWT150rF25eicRJrg_WPipIxCWDelCHElBI,21841
16
+ promptbuilder/llm_client/main.py,sha256=k4JTyKq2atNyFtI1bjjqXEnGSEugj4xk0AJEvHJiMig,8310
17
+ promptbuilder/llm_client/openai_client.py,sha256=5yvjp-Zzp4JsBC9_ffSb1A9-iMG4Lu2B2et2CdtK9R0,22864
18
18
  promptbuilder/llm_client/types.py,sha256=2E-aPRb5uAkLFJocmjF1Lh2aQRq9r8a5JRIw-duHfjA,7460
19
19
  promptbuilder/llm_client/utils.py,sha256=79lvSppjrrItHB5MIozbp_5Oq7TsOK4Qzt9Ae3XMLFw,7624
20
- promptbuilder-0.4.17.dist-info/licenses/LICENSE,sha256=fqXmInzgsvEOIaKSBgcrwKyYCGYF0MKErJ0YivtODcc,1096
21
- promptbuilder-0.4.17.dist-info/METADATA,sha256=6kQc71NIDecORLkTH5Gmn3TuZG2BPdG_5sq7cNAbEFs,3722
22
- promptbuilder-0.4.17.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
23
- promptbuilder-0.4.17.dist-info/top_level.txt,sha256=UBVcYn4UgrPy3O3fmmnPEU_kieuplBMgheetIMei4EI,14
24
- promptbuilder-0.4.17.dist-info/RECORD,,
20
+ promptbuilder-0.4.18.dist-info/licenses/LICENSE,sha256=fqXmInzgsvEOIaKSBgcrwKyYCGYF0MKErJ0YivtODcc,1096
21
+ promptbuilder-0.4.18.dist-info/METADATA,sha256=bbynjS91gKgHZKKCzw1VgD2FgI54Orn5OLRUqZJsQmA,3738
22
+ promptbuilder-0.4.18.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
23
+ promptbuilder-0.4.18.dist-info/top_level.txt,sha256=UBVcYn4UgrPy3O3fmmnPEU_kieuplBMgheetIMei4EI,14
24
+ promptbuilder-0.4.18.dist-info/RECORD,,