hamtaa-texttools 1.1.2__py3-none-any.whl → 1.1.4__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hamtaa-texttools
3
- Version: 1.1.2
3
+ Version: 1.1.4
4
4
  Summary: A high-level NLP toolkit built on top of modern LLMs.
5
5
  Author-email: Tohidi <the.mohammad.tohidi@gmail.com>, Montazer <montazerh82@gmail.com>, Givechi <mohamad.m.givechi@gmail.com>, MoosaviNejad <erfanmoosavi84@gmail.com>
6
6
  License: MIT License
@@ -40,14 +40,14 @@ Dynamic: license-file
40
40
 
41
41
  It provides both **sync (`TheTool`)** and **async (`AsyncTheTool`)** APIs for maximum flexibility.
42
42
 
43
- It provides ready-to-use utilities for **translation, question detection, keyword extraction, categorization, NER extractor, and more** — designed to help you integrate AI-powered text processing into your applications with minimal effort.
43
+ It provides ready-to-use utilities for **translation, question detection, keyword extraction, categorization, NER extraction, and more** — designed to help you integrate AI-powered text processing into your applications with minimal effort.
44
44
 
45
45
  ---
46
46
 
47
47
  ## ✨ Features
48
48
 
49
49
  TextTools provides a rich collection of high-level NLP utilities built on top of LLMs.
50
- Each tool is designed to work out-of-the-box with structured outputs (JSON / Pydantic).
50
+ Each tool is designed to work with structured outputs (JSON / Pydantic).
51
51
 
52
52
  - **`categorize()`** - Classifies text into Islamic studies categories
53
53
  - **`is_question()`** - Binary detection of whether input is a question
@@ -63,7 +63,7 @@ Each tool is designed to work out-of-the-box with structured outputs (JSON / Pyd
63
63
 
64
64
  ---
65
65
 
66
- ## ⚙️ `with_analysis`, `logprobs`, `output_lang`, `user_prompt` and `temperature` parameters
66
+ ## ⚙️ `with_analysis`, `logprobs`, `output_lang`, `user_prompt`, `temperature` and `validator` parameters
67
67
 
68
68
  TextTools provides several optional flags to customize LLM behavior:
69
69
 
@@ -78,6 +78,8 @@ Note: This doubles token usage per call because it triggers an additional LLM re
78
78
 
79
79
  - **`temperature=0.0`** → Determines how creative the model should respond. Takes a float number from `0.0` to `1.0`.
80
80
 
81
+ - **`validator=validation_function`** → Forces TheTool to validate the output result based on your custom validator. Validator should return bool (True if there were no problem, False if the validation failed.) If validator failed, TheTool will retry to get another output by modifying `temperature`.
82
+
81
83
  All these parameters can be used individually or together to tailor the behavior of any tool in **TextTools**.
82
84
 
83
85
  **Note:** There might be some tools that don't support some of the parameters above.
@@ -1,4 +1,4 @@
1
- hamtaa_texttools-1.1.2.dist-info/licenses/LICENSE,sha256=Hb2YOBKy2MJQLnyLrX37B4ZVuac8eaIcE71SvVIMOLg,1082
1
+ hamtaa_texttools-1.1.4.dist-info/licenses/LICENSE,sha256=Hb2YOBKy2MJQLnyLrX37B4ZVuac8eaIcE71SvVIMOLg,1082
2
2
  texttools/__init__.py,sha256=v3tQCH_Cjj47fCpuhK6sKSVAqEjNkc-cZbY4OJa4IZw,202
3
3
  texttools/batch/__init__.py,sha256=q50JsQsmQGp_8RW0KNasYeYWVV0R4FUNZ-ujXwEJemY,143
4
4
  texttools/batch/batch_manager.py,sha256=UCJaOq-tTy6kTZJvFuBDBSmzlDeVlLTeFlR83e6eXkQ,8808
@@ -16,15 +16,15 @@ texttools/prompts/summarize.yaml,sha256=o6rxGPfWtZd61Duvm8NVvCJqfq73b-wAuMSKR6UY
16
16
  texttools/prompts/text_to_question.yaml,sha256=UheKYpDn6iyKI8NxunHZtFpNyfCLZZe5cvkuXpurUJY,783
17
17
  texttools/prompts/translate.yaml,sha256=mGT2uBCei6uucWqVbs4silk-UV060v3G0jnt0P6sr50,634
18
18
  texttools/tools/__init__.py,sha256=hG1I28Q7BJ1Dbs95x6QMKXdsAlC5Eh_tqC-EbAibwiU,114
19
- texttools/tools/async_the_tool.py,sha256=ORn3xk6zJ3HdDNo_zj9cTlY05zsQ1un5H96xLIUUOg4,14446
20
- texttools/tools/the_tool.py,sha256=q-bvYv38CuBMstYOV_42zv2frHgsaLRzo_XAGNrdNWA,14212
21
- texttools/tools/internals/async_operator.py,sha256=vZvU5XPdNKz--ZYheEQOIRzVNi-Ni1x9GxgcDBlbYJM,6760
22
- texttools/tools/internals/base_operator.py,sha256=3GUSEN87Y_1CqkeK_QXkFG8O7GPliGSVUtiPp1taQRM,3051
19
+ texttools/tools/async_the_tool.py,sha256=2ZY7Lo6Jj9xoTF8bfdh_g8VOXZ7ljMMesd1_QHXyf4s,15395
20
+ texttools/tools/the_tool.py,sha256=XKgZuzriFnk8B-YihJfs6BKivxjGCgOFfe7hnCpEiXs,15161
21
+ texttools/tools/internals/async_operator.py,sha256=pqxceWej3wJmL2RSYEWdowO77MVEN6E7kqppOnsoLOk,9069
22
+ texttools/tools/internals/base_operator.py,sha256=7xRNKyPnh61XTvgPghyQeclBlhw7K7hZxk10ZMC9CQY,3492
23
23
  texttools/tools/internals/formatters.py,sha256=tACNLP6PeoqaRpNudVxBaHA25zyWqWYPZQuYysIu88g,941
24
- texttools/tools/internals/operator.py,sha256=M-0-6SmRmW7PX4CWhMAgoSwtk_2w1_YrItK3FhdObCU,6659
24
+ texttools/tools/internals/operator.py,sha256=RqCau1F1lxoDQq4BqJvjOnwaf-86SQF_wpoP2V3LYKQ,8951
25
25
  texttools/tools/internals/output_models.py,sha256=gbVbzBWeyHUVNsCBuawdgz9ZEzsC7wfygGgZJsAaexY,1662
26
26
  texttools/tools/internals/prompt_loader.py,sha256=1khayXcRC5w0Vf2SufpNaN1IUIhbKzS5ATiKheoBcGE,2082
27
- hamtaa_texttools-1.1.2.dist-info/METADATA,sha256=J2YfhGNN2SpOq5P3iOsniaUzpuUaP20dTlPBiQX6Gss,7144
28
- hamtaa_texttools-1.1.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
29
- hamtaa_texttools-1.1.2.dist-info/top_level.txt,sha256=5Mh0jIxxZ5rOXHGJ6Mp-JPKviywwN0MYuH0xk5bEWqE,10
30
- hamtaa_texttools-1.1.2.dist-info/RECORD,,
27
+ hamtaa_texttools-1.1.4.dist-info/METADATA,sha256=-pHGh4p8ZW1agur7LwjY8EUZps9AU9TTWtxxkbleDAw,7449
28
+ hamtaa_texttools-1.1.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
29
+ hamtaa_texttools-1.1.4.dist-info/top_level.txt,sha256=5Mh0jIxxZ5rOXHGJ6Mp-JPKviywwN0MYuH0xk5bEWqE,10
30
+ hamtaa_texttools-1.1.4.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
- from typing import Literal, Any
1
+ from typing import Literal, Any, Callable
2
2
 
3
3
  from openai import AsyncOpenAI
4
4
 
@@ -34,6 +34,7 @@ class AsyncTheTool:
34
34
  temperature: float | None = 0.0,
35
35
  logprobs: bool = False,
36
36
  top_logprobs: int | None = None,
37
+ validator: Callable[[Any], bool] | None = None,
37
38
  ) -> OutputModels.ToolOutput:
38
39
  """
39
40
  Categorize a text into a single Islamic studies domain category.
@@ -52,6 +53,7 @@ class AsyncTheTool:
52
53
  temperature=temperature,
53
54
  logprobs=logprobs,
54
55
  top_logprobs=top_logprobs,
56
+ validator=validator,
55
57
  # Internal parameters
56
58
  prompt_file="categorizer.yaml",
57
59
  output_model=OutputModels.CategorizerOutput,
@@ -69,6 +71,7 @@ class AsyncTheTool:
69
71
  temperature: float | None = 0.0,
70
72
  logprobs: bool = False,
71
73
  top_logprobs: int | None = None,
74
+ validator: Callable[[Any], bool] | None = None,
72
75
  ) -> OutputModels.ToolOutput:
73
76
  """
74
77
  Extract salient keywords from text.
@@ -88,6 +91,7 @@ class AsyncTheTool:
88
91
  temperature=temperature,
89
92
  logprobs=logprobs,
90
93
  top_logprobs=top_logprobs,
94
+ validator=validator,
91
95
  # Internal parameters
92
96
  prompt_file="extract_keywords.yaml",
93
97
  output_model=OutputModels.ListStrOutput,
@@ -104,6 +108,7 @@ class AsyncTheTool:
104
108
  temperature: float | None = 0.0,
105
109
  logprobs: bool = False,
106
110
  top_logprobs: int | None = None,
111
+ validator: Callable[[Any], bool] | None = None,
107
112
  ) -> OutputModels.ToolOutput:
108
113
  """
109
114
  Perform Named Entity Recognition (NER) over the input text.
@@ -123,6 +128,7 @@ class AsyncTheTool:
123
128
  temperature=temperature,
124
129
  logprobs=logprobs,
125
130
  top_logprobs=top_logprobs,
131
+ validator=validator,
126
132
  # Internal parameters
127
133
  prompt_file="extract_entities.yaml",
128
134
  output_model=OutputModels.ListDictStrStrOutput,
@@ -138,6 +144,7 @@ class AsyncTheTool:
138
144
  temperature: float | None = 0.0,
139
145
  logprobs: bool = False,
140
146
  top_logprobs: int | None = None,
147
+ validator: Callable[[Any], bool] | None = None,
141
148
  ) -> OutputModels.ToolOutput:
142
149
  """
143
150
  Detect if the input is phrased as a question.
@@ -156,6 +163,7 @@ class AsyncTheTool:
156
163
  temperature=temperature,
157
164
  logprobs=logprobs,
158
165
  top_logprobs=top_logprobs,
166
+ validator=validator,
159
167
  # Internal parameters
160
168
  prompt_file="is_question.yaml",
161
169
  output_model=OutputModels.BoolOutput,
@@ -173,6 +181,7 @@ class AsyncTheTool:
173
181
  temperature: float | None = 0.0,
174
182
  logprobs: bool = False,
175
183
  top_logprobs: int | None = None,
184
+ validator: Callable[[Any], bool] | None = None,
176
185
  ) -> OutputModels.ToolOutput:
177
186
  """
178
187
  Generate a single question from the given text.
@@ -192,6 +201,7 @@ class AsyncTheTool:
192
201
  temperature=temperature,
193
202
  logprobs=logprobs,
194
203
  top_logprobs=top_logprobs,
204
+ validator=validator,
195
205
  # Internal parameters
196
206
  prompt_file="text_to_question.yaml",
197
207
  output_model=OutputModels.StrOutput,
@@ -209,6 +219,7 @@ class AsyncTheTool:
209
219
  logprobs: bool = False,
210
220
  top_logprobs: int | None = None,
211
221
  mode: Literal["default", "reason"] = "default",
222
+ validator: Callable[[Any], bool] | None = None,
212
223
  ) -> OutputModels.ToolOutput:
213
224
  """
214
225
  Merge multiple questions into a single unified question.
@@ -229,6 +240,7 @@ class AsyncTheTool:
229
240
  temperature=temperature,
230
241
  logprobs=logprobs,
231
242
  top_logprobs=top_logprobs,
243
+ validator=validator,
232
244
  # Internal parameters
233
245
  prompt_file="merge_questions.yaml",
234
246
  output_model=OutputModels.StrOutput,
@@ -246,6 +258,7 @@ class AsyncTheTool:
246
258
  logprobs: bool = False,
247
259
  top_logprobs: int | None = None,
248
260
  mode: Literal["positive", "negative", "hard_negative"] = "positive",
261
+ validator: Callable[[Any], bool] | None = None,
249
262
  ) -> OutputModels.ToolOutput:
250
263
  """
251
264
  Rewrite a text with different modes.
@@ -265,6 +278,7 @@ class AsyncTheTool:
265
278
  temperature=temperature,
266
279
  logprobs=logprobs,
267
280
  top_logprobs=top_logprobs,
281
+ validator=validator,
268
282
  # Internal parameters
269
283
  prompt_file="rewrite.yaml",
270
284
  output_model=OutputModels.StrOutput,
@@ -282,6 +296,7 @@ class AsyncTheTool:
282
296
  temperature: float | None = 0.0,
283
297
  logprobs: bool = False,
284
298
  top_logprobs: int | None = None,
299
+ validator: Callable[[Any], bool] | None = None,
285
300
  ) -> OutputModels.ToolOutput:
286
301
  """
287
302
  Generate a list of questions about a subject.
@@ -302,6 +317,7 @@ class AsyncTheTool:
302
317
  temperature=temperature,
303
318
  logprobs=logprobs,
304
319
  top_logprobs=top_logprobs,
320
+ validator=validator,
305
321
  # Internal parameters
306
322
  prompt_file="subject_to_question.yaml",
307
323
  output_model=OutputModels.ReasonListStrOutput,
@@ -318,6 +334,7 @@ class AsyncTheTool:
318
334
  temperature: float | None = 0.0,
319
335
  logprobs: bool = False,
320
336
  top_logprobs: int | None = None,
337
+ validator: Callable[[Any], bool] | None = None,
321
338
  ) -> OutputModels.ToolOutput:
322
339
  """
323
340
  Summarize the given subject text.
@@ -337,6 +354,7 @@ class AsyncTheTool:
337
354
  temperature=temperature,
338
355
  logprobs=logprobs,
339
356
  top_logprobs=top_logprobs,
357
+ validator=validator,
340
358
  # Internal parameters
341
359
  prompt_file="summarize.yaml",
342
360
  output_model=OutputModels.StrOutput,
@@ -353,6 +371,7 @@ class AsyncTheTool:
353
371
  temperature: float | None = 0.0,
354
372
  logprobs: bool = False,
355
373
  top_logprobs: int | None = None,
374
+ validator: Callable[[Any], bool] | None = None,
356
375
  ) -> OutputModels.ToolOutput:
357
376
  """
358
377
  Translate text between languages.
@@ -372,6 +391,7 @@ class AsyncTheTool:
372
391
  temperature=temperature,
373
392
  logprobs=logprobs,
374
393
  top_logprobs=top_logprobs,
394
+ validator=validator,
375
395
  # Internal parameters
376
396
  prompt_file="translate.yaml",
377
397
  output_model=OutputModels.StrOutput,
@@ -411,4 +431,5 @@ class AsyncTheTool:
411
431
  user_prompt=None,
412
432
  with_analysis=False,
413
433
  mode=None,
434
+ validator=None,
414
435
  )
@@ -1,4 +1,4 @@
1
- from typing import Any, TypeVar, Type, Literal
1
+ from typing import Any, TypeVar, Type, Literal, Callable
2
2
  import logging
3
3
 
4
4
  from openai import AsyncOpenAI
@@ -115,6 +115,7 @@ class AsyncOperator(BaseOperator):
115
115
  temperature: float,
116
116
  logprobs: bool,
117
117
  top_logprobs: int | None,
118
+ validator: Callable[[Any], bool] | None,
118
119
  # Internal parameters
119
120
  prompt_file: str,
120
121
  output_model: Type[T],
@@ -179,6 +180,55 @@ class AsyncOperator(BaseOperator):
179
180
 
180
181
  output.result = parsed.result
181
182
 
183
+ # Retry logic if validation fails
184
+ if validator and not validator(output.result):
185
+ max_retries = 3
186
+ for attempt in range(max_retries):
187
+ logger.warning(
188
+ f"Validation failed, retrying for the {attempt + 1} time."
189
+ )
190
+
191
+ # Generate new temperature for retry
192
+ retry_temperature = self._get_retry_temp(temperature)
193
+ try:
194
+ if resp_format == "vllm":
195
+ parsed, completion = await self._vllm_completion(
196
+ messages,
197
+ output_model,
198
+ retry_temperature,
199
+ logprobs,
200
+ top_logprobs,
201
+ )
202
+ elif resp_format == "parse":
203
+ parsed, completion = await self._parse_completion(
204
+ messages,
205
+ output_model,
206
+ retry_temperature,
207
+ logprobs,
208
+ top_logprobs,
209
+ )
210
+
211
+ output.result = parsed.result
212
+
213
+ # Check if retry was successful
214
+ if validator(output.result):
215
+ logger.info(
216
+ f"Validation passed on retry attempt {attempt + 1}"
217
+ )
218
+ break
219
+ else:
220
+ logger.warning(
221
+ f"Validation still failing after retry attempt {attempt + 1}"
222
+ )
223
+
224
+ except Exception as e:
225
+ logger.error(f"Retry attempt {attempt + 1} failed: {e}")
226
+ # Continue to next retry attempt if this one fails
227
+
228
+ # Final check after all retries
229
+ if validator and not validator(output.result):
230
+ output.errors.append("Validation failed after all retry attempts")
231
+
182
232
  if logprobs:
183
233
  output.logprobs = self._extract_logprobs(completion)
184
234
 
@@ -3,6 +3,7 @@ import json
3
3
  import re
4
4
  import math
5
5
  import logging
6
+ import random
6
7
 
7
8
  from pydantic import BaseModel
8
9
  from openai import OpenAI, AsyncOpenAI
@@ -86,3 +87,15 @@ class BaseOperator:
86
87
  logprobs_data.append(token_entry)
87
88
 
88
89
  return logprobs_data
90
+
91
+ def _get_retry_temp(self, base_temp: float) -> float:
92
+ """
93
+ Calculate temperature for retry attempts.
94
+ """
95
+ delta_temp = random.choice([-1, 1]) * random.uniform(0.1, 0.9)
96
+ new_temp = base_temp + delta_temp
97
+ print(f"Base Temp: {base_temp}")
98
+ print(f"Delta Temp: {delta_temp}")
99
+ print(f"New Temp: {new_temp}")
100
+
101
+ return max(0.0, min(new_temp, 1.5))
@@ -1,4 +1,4 @@
1
- from typing import Any, TypeVar, Type, Literal
1
+ from typing import Any, TypeVar, Type, Literal, Callable
2
2
  import logging
3
3
 
4
4
  from openai import OpenAI
@@ -115,6 +115,7 @@ class Operator(BaseOperator):
115
115
  temperature: float,
116
116
  logprobs: bool,
117
117
  top_logprobs: int | None,
118
+ validator: Callable[[Any], bool] | None,
118
119
  # Internal parameters
119
120
  prompt_file: str,
120
121
  output_model: Type[T],
@@ -179,6 +180,55 @@ class Operator(BaseOperator):
179
180
 
180
181
  output.result = parsed.result
181
182
 
183
+ # Retry logic if validation fails
184
+ if validator and not validator(output.result):
185
+ max_retries = 3
186
+ for attempt in range(max_retries):
187
+ logger.warning(
188
+ f"Validation failed, retrying for the {attempt + 1} time."
189
+ )
190
+
191
+ # Generate new temperature for retry
192
+ retry_temperature = self._get_retry_temp(temperature)
193
+ try:
194
+ if resp_format == "vllm":
195
+ parsed, completion = self._vllm_completion(
196
+ messages,
197
+ output_model,
198
+ retry_temperature,
199
+ logprobs,
200
+ top_logprobs,
201
+ )
202
+ elif resp_format == "parse":
203
+ parsed, completion = self._parse_completion(
204
+ messages,
205
+ output_model,
206
+ retry_temperature,
207
+ logprobs,
208
+ top_logprobs,
209
+ )
210
+
211
+ output.result = parsed.result
212
+
213
+ # Check if retry was successful
214
+ if validator(output.result):
215
+ logger.info(
216
+ f"Validation passed on retry attempt {attempt + 1}"
217
+ )
218
+ break
219
+ else:
220
+ logger.warning(
221
+ f"Validation still failing after retry attempt {attempt + 1}"
222
+ )
223
+
224
+ except Exception as e:
225
+ logger.error(f"Retry attempt {attempt + 1} failed: {e}")
226
+ # Continue to next retry attempt if this one fails
227
+
228
+ # Final check after all retries
229
+ if validator and not validator(output.result):
230
+ output.errors.append("Validation failed after all retry attempts")
231
+
182
232
  if logprobs:
183
233
  output.logprobs = self._extract_logprobs(completion)
184
234
 
@@ -188,5 +238,5 @@ class Operator(BaseOperator):
188
238
  return output
189
239
 
190
240
  except Exception as e:
191
- logger.error(f"AsyncTheTool failed: {e}")
241
+ logger.error(f"TheTool failed: {e}")
192
242
  return output.errors.append(str(e))
@@ -1,4 +1,4 @@
1
- from typing import Literal, Any
1
+ from typing import Literal, Any, Callable
2
2
 
3
3
  from openai import OpenAI
4
4
 
@@ -32,6 +32,7 @@ class TheTool:
32
32
  temperature: float | None = 0.0,
33
33
  logprobs: bool = False,
34
34
  top_logprobs: int | None = None,
35
+ validator: Callable[[Any], bool] | None = None,
35
36
  ) -> OutputModels.ToolOutput:
36
37
  """
37
38
  Categorize a text into a single Islamic studies domain category.
@@ -50,6 +51,7 @@ class TheTool:
50
51
  temperature=temperature,
51
52
  logprobs=logprobs,
52
53
  top_logprobs=top_logprobs,
54
+ validator=validator,
53
55
  # Internal parameters
54
56
  prompt_file="categorizer.yaml",
55
57
  output_model=OutputModels.CategorizerOutput,
@@ -67,6 +69,7 @@ class TheTool:
67
69
  temperature: float | None = 0.0,
68
70
  logprobs: bool = False,
69
71
  top_logprobs: int | None = None,
72
+ validator: Callable[[Any], bool] | None = None,
70
73
  ) -> OutputModels.ToolOutput:
71
74
  """
72
75
  Extract salient keywords from text.
@@ -86,6 +89,7 @@ class TheTool:
86
89
  temperature=temperature,
87
90
  logprobs=logprobs,
88
91
  top_logprobs=top_logprobs,
92
+ validator=validator,
89
93
  # Internal parameters
90
94
  prompt_file="extract_keywords.yaml",
91
95
  output_model=OutputModels.ListStrOutput,
@@ -102,6 +106,7 @@ class TheTool:
102
106
  temperature: float | None = 0.0,
103
107
  logprobs: bool = False,
104
108
  top_logprobs: int | None = None,
109
+ validator: Callable[[Any], bool] | None = None,
105
110
  ) -> OutputModels.ToolOutput:
106
111
  """
107
112
  Perform Named Entity Recognition (NER) over the input text.
@@ -121,6 +126,7 @@ class TheTool:
121
126
  temperature=temperature,
122
127
  logprobs=logprobs,
123
128
  top_logprobs=top_logprobs,
129
+ validator=validator,
124
130
  # Internal parameters
125
131
  prompt_file="extract_entities.yaml",
126
132
  output_model=OutputModels.ListDictStrStrOutput,
@@ -136,6 +142,7 @@ class TheTool:
136
142
  temperature: float | None = 0.0,
137
143
  logprobs: bool = False,
138
144
  top_logprobs: int | None = None,
145
+ validator: Callable[[Any], bool] | None = None,
139
146
  ) -> OutputModels.ToolOutput:
140
147
  """
141
148
  Detect if the input is phrased as a question.
@@ -154,6 +161,7 @@ class TheTool:
154
161
  temperature=temperature,
155
162
  logprobs=logprobs,
156
163
  top_logprobs=top_logprobs,
164
+ validator=validator,
157
165
  # Internal parameters
158
166
  prompt_file="is_question.yaml",
159
167
  output_model=OutputModels.BoolOutput,
@@ -171,6 +179,7 @@ class TheTool:
171
179
  temperature: float | None = 0.0,
172
180
  logprobs: bool = False,
173
181
  top_logprobs: int | None = None,
182
+ validator: Callable[[Any], bool] | None = None,
174
183
  ) -> OutputModels.ToolOutput:
175
184
  """
176
185
  Generate a single question from the given text.
@@ -190,6 +199,7 @@ class TheTool:
190
199
  temperature=temperature,
191
200
  logprobs=logprobs,
192
201
  top_logprobs=top_logprobs,
202
+ validator=validator,
193
203
  # Internal parameters
194
204
  prompt_file="text_to_question.yaml",
195
205
  output_model=OutputModels.StrOutput,
@@ -207,6 +217,7 @@ class TheTool:
207
217
  logprobs: bool = False,
208
218
  top_logprobs: int | None = None,
209
219
  mode: Literal["default", "reason"] = "default",
220
+ validator: Callable[[Any], bool] | None = None,
210
221
  ) -> OutputModels.ToolOutput:
211
222
  """
212
223
  Merge multiple questions into a single unified question.
@@ -227,6 +238,7 @@ class TheTool:
227
238
  temperature=temperature,
228
239
  logprobs=logprobs,
229
240
  top_logprobs=top_logprobs,
241
+ validator=validator,
230
242
  # Internal parameters
231
243
  prompt_file="merge_questions.yaml",
232
244
  output_model=OutputModels.StrOutput,
@@ -244,6 +256,7 @@ class TheTool:
244
256
  logprobs: bool = False,
245
257
  top_logprobs: int | None = None,
246
258
  mode: Literal["positive", "negative", "hard_negative"] = "positive",
259
+ validator: Callable[[Any], bool] | None = None,
247
260
  ) -> OutputModels.ToolOutput:
248
261
  """
249
262
  Rewrite a text with different modes.
@@ -263,6 +276,7 @@ class TheTool:
263
276
  temperature=temperature,
264
277
  logprobs=logprobs,
265
278
  top_logprobs=top_logprobs,
279
+ validator=validator,
266
280
  # Internal parameters
267
281
  prompt_file="rewrite.yaml",
268
282
  output_model=OutputModels.StrOutput,
@@ -280,6 +294,7 @@ class TheTool:
280
294
  temperature: float | None = 0.0,
281
295
  logprobs: bool = False,
282
296
  top_logprobs: int | None = None,
297
+ validator: Callable[[Any], bool] | None = None,
283
298
  ) -> OutputModels.ToolOutput:
284
299
  """
285
300
  Generate a list of questions about a subject.
@@ -300,6 +315,7 @@ class TheTool:
300
315
  temperature=temperature,
301
316
  logprobs=logprobs,
302
317
  top_logprobs=top_logprobs,
318
+ validator=validator,
303
319
  # Internal parameters
304
320
  prompt_file="subject_to_question.yaml",
305
321
  output_model=OutputModels.ReasonListStrOutput,
@@ -316,6 +332,7 @@ class TheTool:
316
332
  temperature: float | None = 0.0,
317
333
  logprobs: bool = False,
318
334
  top_logprobs: int | None = None,
335
+ validator: Callable[[Any], bool] | None = None,
319
336
  ) -> OutputModels.ToolOutput:
320
337
  """
321
338
  Summarize the given subject text.
@@ -335,6 +352,7 @@ class TheTool:
335
352
  temperature=temperature,
336
353
  logprobs=logprobs,
337
354
  top_logprobs=top_logprobs,
355
+ validator=validator,
338
356
  # Internal parameters
339
357
  prompt_file="summarize.yaml",
340
358
  output_model=OutputModels.StrOutput,
@@ -351,6 +369,7 @@ class TheTool:
351
369
  temperature: float | None = 0.0,
352
370
  logprobs: bool = False,
353
371
  top_logprobs: int | None = None,
372
+ validator: Callable[[Any], bool] | None = None,
354
373
  ) -> OutputModels.ToolOutput:
355
374
  """
356
375
  Translate text between languages.
@@ -370,6 +389,7 @@ class TheTool:
370
389
  temperature=temperature,
371
390
  logprobs=logprobs,
372
391
  top_logprobs=top_logprobs,
392
+ validator=validator,
373
393
  # Internal parameters
374
394
  prompt_file="translate.yaml",
375
395
  output_model=OutputModels.StrOutput,
@@ -409,4 +429,5 @@ class TheTool:
409
429
  user_prompt=None,
410
430
  with_analysis=False,
411
431
  mode=None,
432
+ validator=None,
412
433
  )