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.
- {hamtaa_texttools-1.1.2.dist-info → hamtaa_texttools-1.1.4.dist-info}/METADATA +6 -4
- {hamtaa_texttools-1.1.2.dist-info → hamtaa_texttools-1.1.4.dist-info}/RECORD +10 -10
- texttools/tools/async_the_tool.py +22 -1
- texttools/tools/internals/async_operator.py +51 -1
- texttools/tools/internals/base_operator.py +13 -0
- texttools/tools/internals/operator.py +52 -2
- texttools/tools/the_tool.py +22 -1
- {hamtaa_texttools-1.1.2.dist-info → hamtaa_texttools-1.1.4.dist-info}/WHEEL +0 -0
- {hamtaa_texttools-1.1.2.dist-info → hamtaa_texttools-1.1.4.dist-info}/licenses/LICENSE +0 -0
- {hamtaa_texttools-1.1.2.dist-info → hamtaa_texttools-1.1.4.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hamtaa-texttools
|
|
3
|
-
Version: 1.1.
|
|
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
|
|
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
|
|
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 `
|
|
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.
|
|
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=
|
|
20
|
-
texttools/tools/the_tool.py,sha256=
|
|
21
|
-
texttools/tools/internals/async_operator.py,sha256=
|
|
22
|
-
texttools/tools/internals/base_operator.py,sha256=
|
|
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=
|
|
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.
|
|
28
|
-
hamtaa_texttools-1.1.
|
|
29
|
-
hamtaa_texttools-1.1.
|
|
30
|
-
hamtaa_texttools-1.1.
|
|
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"
|
|
241
|
+
logger.error(f"TheTool failed: {e}")
|
|
192
242
|
return output.errors.append(str(e))
|
texttools/tools/the_tool.py
CHANGED
|
@@ -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
|
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|