hamtaa-texttools 1.1.14__py3-none-any.whl → 1.1.15__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.14
3
+ Version: 1.1.15
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
@@ -95,6 +95,7 @@ Every tool of `TextTools` returns a `ToolOutput` object which is a BaseModel wit
95
95
  - **`result (Any)`** → The output of LLM
96
96
  - **`analysis (str)`** → The reasoning step before generating the final output
97
97
  - **`logprobs (list)`** → Token-level probabilities for the generated output
98
+ - **`process (str)`** → The tool name which processed the input
98
99
  - **`errors (list[str])`** → Any error that have occured during calling LLM
99
100
 
100
101
  **Note:** You can use `repr(ToolOutput)` to see details of an output.
@@ -1,4 +1,4 @@
1
- hamtaa_texttools-1.1.14.dist-info/licenses/LICENSE,sha256=Hb2YOBKy2MJQLnyLrX37B4ZVuac8eaIcE71SvVIMOLg,1082
1
+ hamtaa_texttools-1.1.15.dist-info/licenses/LICENSE,sha256=Hb2YOBKy2MJQLnyLrX37B4ZVuac8eaIcE71SvVIMOLg,1082
2
2
  texttools/__init__.py,sha256=dc81lXGWP29k7oVvq2BMoMotz6lgiwX4PO2jHHBe2S8,317
3
3
  texttools/batch/batch_config.py,sha256=m1UgILVKjNdWE6laNbfbG4vgi4o2fEegGZbeoam6pnY,749
4
4
  texttools/batch/batch_runner.py,sha256=9e4SPLlvLHHs3U7bHkuuMVw8TFNwsGUzRjkAMKN4_ik,9378
@@ -17,15 +17,15 @@ texttools/prompts/subject_to_question.yaml,sha256=C7x7rNNm6U_ZG9HOn6zuzYOtvJUZ2s
17
17
  texttools/prompts/summarize.yaml,sha256=o6rxGPfWtZd61Duvm8NVvCJqfq73b-wAuMSKR6UYUqY,459
18
18
  texttools/prompts/text_to_question.yaml,sha256=UheKYpDn6iyKI8NxunHZtFpNyfCLZZe5cvkuXpurUJY,783
19
19
  texttools/prompts/translate.yaml,sha256=mGT2uBCei6uucWqVbs4silk-UV060v3G0jnt0P6sr50,634
20
- texttools/tools/async_tools.py,sha256=2bWwHd5eaUZwEt4u0rsl6K7QTpE0r83sd8nGaMqStyA,31994
21
- texttools/tools/sync_tools.py,sha256=DduJMkHtP0pLiEVbGtfuVq__kVhyMy8Hwi528OusyGc,31747
22
- texttools/tools/internals/async_operator.py,sha256=kVYClefPlcIhaMwcfh2rNX0GROaStjXdVe6bh_XTGKM,7149
20
+ texttools/tools/async_tools.py,sha256=vNAg0gxwUZPsMS4q8JCv7RlYymS8l_5FsFI5adEYT7w,34376
21
+ texttools/tools/sync_tools.py,sha256=hFifFa9YatvSeGif2E_bIG006eMdIBr6SV9HsZ_dAlg,34187
22
+ texttools/tools/internals/async_operator.py,sha256=1TMr8e1qbE9GSz8jl0q3MKdM8lIYE-1ZuSxHjYPqKHI,7198
23
23
  texttools/tools/internals/formatters.py,sha256=tACNLP6PeoqaRpNudVxBaHA25zyWqWYPZQuYysIu88g,941
24
- texttools/tools/internals/models.py,sha256=VH9l4d_ER8skBCTj5w9ISdRnsUXb3H2OVehz9r7VgdM,5630
24
+ texttools/tools/internals/models.py,sha256=w1FveT2lqZiAzhTGwghMJrePyfO43OjpIWbnJFDRPcg,5842
25
25
  texttools/tools/internals/operator_utils.py,sha256=w1k0RJ_W_CRbVc_J2w337VuL-opHpHiCxfhEOwtyuOo,1856
26
26
  texttools/tools/internals/prompt_loader.py,sha256=4g6-U8kqrGN7VpNaRcrBcnF-h03PXjUDBP0lL0_4EZY,1953
27
- texttools/tools/internals/sync_operator.py,sha256=5kZWO8CGgoXx1FGFOWU1wnj2RWW8_KNEMGnQCkmbYwA,7057
28
- hamtaa_texttools-1.1.14.dist-info/METADATA,sha256=Smh1J0R1JjMkeNOwc-bIEsAVDexdERwRM3T6ZpBcDkk,9370
29
- hamtaa_texttools-1.1.14.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
30
- hamtaa_texttools-1.1.14.dist-info/top_level.txt,sha256=5Mh0jIxxZ5rOXHGJ6Mp-JPKviywwN0MYuH0xk5bEWqE,10
31
- hamtaa_texttools-1.1.14.dist-info/RECORD,,
27
+ texttools/tools/internals/sync_operator.py,sha256=4-V__o55Q8w29lWxkhG4St-exZLZTfBbiW76knOXbc0,7106
28
+ hamtaa_texttools-1.1.15.dist-info/METADATA,sha256=724US-ncgD_YZEqzMXc010bMR1KOWuk_9jyl2jNIbys,9437
29
+ hamtaa_texttools-1.1.15.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
30
+ hamtaa_texttools-1.1.15.dist-info/top_level.txt,sha256=5Mh0jIxxZ5rOXHGJ6Mp-JPKviywwN0MYuH0xk5bEWqE,10
31
+ hamtaa_texttools-1.1.15.dist-info/RECORD,,
@@ -1,3 +1,4 @@
1
+ from datetime import datetime
1
2
  from typing import Literal, Any
2
3
  from collections.abc import Callable
3
4
 
@@ -63,10 +64,12 @@ class AsyncTheTool:
63
64
  - analysis (str | None): Detailed reasoning if with_analysis enabled
64
65
  - errors (list(str) | None): Errors occured during tool call
65
66
  """
67
+ start = datetime.now()
68
+
66
69
  if mode == "category_tree":
67
70
  # Initializations
68
71
  output = Models.ToolOutput()
69
- levels = categories.level_count()
72
+ levels = categories.get_level_count()
70
73
  parent_id = 0
71
74
  final_output = []
72
75
 
@@ -80,6 +83,8 @@ class AsyncTheTool:
80
83
  output.errors.append(
81
84
  f"No categories found for parent_id {parent_id} in the tree"
82
85
  )
86
+ end = datetime.now()
87
+ output.execution_time = (end - start).total_seconds()
83
88
  return output
84
89
 
85
90
  # Extract category names and descriptions
@@ -111,6 +116,8 @@ class AsyncTheTool:
111
116
  # Check for errors from operator
112
117
  if level_output.errors:
113
118
  output.errors.extend(level_output.errors)
119
+ end = datetime.now()
120
+ output.execution_time = (end - start).total_seconds()
114
121
  return output
115
122
 
116
123
  # Get the chosen category
@@ -122,20 +129,25 @@ class AsyncTheTool:
122
129
  output.errors.append(
123
130
  f"Category '{chosen_category}' not found in tree after selection"
124
131
  )
132
+ end = datetime.now()
133
+ output.execution_time = (end - start).total_seconds()
125
134
  return output
126
135
 
127
136
  parent_id = parent_node.node_id
128
137
  final_output.append(parent_node.name)
129
138
 
130
- # Copy analysis/logprobs from the last level's output
139
+ # Copy analysis/logprobs/process from the last level's output
131
140
  output.analysis = level_output.analysis
132
141
  output.logprobs = level_output.logprobs
142
+ output.process = level_output.process
133
143
 
134
144
  output.result = final_output
145
+ end = datetime.now()
146
+ output.execution_time = (end - start).total_seconds()
135
147
  return output
136
148
 
137
149
  else:
138
- return await self._operator.run(
150
+ output = await self._operator.run(
139
151
  # User parameters
140
152
  text=text,
141
153
  category_list=categories,
@@ -152,6 +164,9 @@ class AsyncTheTool:
152
164
  output_model=Models.create_dynamic_model(categories),
153
165
  output_lang=None,
154
166
  )
167
+ end = datetime.now()
168
+ output.execution_time = (end - start).total_seconds()
169
+ return output
155
170
 
156
171
  async def extract_keywords(
157
172
  self,
@@ -190,7 +205,8 @@ class AsyncTheTool:
190
205
  - analysis (str | None): Detailed reasoning if with_analysis enabled
191
206
  - errors (list(str) | None): Errors occured during tool call
192
207
  """
193
- return await self._operator.run(
208
+ start = datetime.now()
209
+ output = await self._operator.run(
194
210
  # User parameters
195
211
  text=text,
196
212
  with_analysis=with_analysis,
@@ -203,11 +219,14 @@ class AsyncTheTool:
203
219
  number_of_keywords=number_of_keywords,
204
220
  validator=validator,
205
221
  max_validation_retries=max_validation_retries,
222
+ priority=priority,
206
223
  # Internal parameters
207
224
  prompt_file="extract_keywords.yaml",
208
225
  output_model=Models.ListStrOutput,
209
- priority=priority,
210
226
  )
227
+ end = datetime.now()
228
+ output.execution_time = (end - start).total_seconds()
229
+ return output
211
230
 
212
231
  async def extract_entities(
213
232
  self,
@@ -244,7 +263,8 @@ class AsyncTheTool:
244
263
  - analysis (str | None): Detailed reasoning if with_analysis enabled
245
264
  - errors (list(str) | None): Errors occured during tool call
246
265
  """
247
- return await self._operator.run(
266
+ start = datetime.now()
267
+ output = await self._operator.run(
248
268
  # User parameters
249
269
  text=text,
250
270
  with_analysis=with_analysis,
@@ -255,12 +275,15 @@ class AsyncTheTool:
255
275
  top_logprobs=top_logprobs,
256
276
  validator=validator,
257
277
  max_validation_retries=max_validation_retries,
278
+ priority=priority,
258
279
  # Internal parameters
259
280
  prompt_file="extract_entities.yaml",
260
281
  output_model=Models.ListDictStrStrOutput,
261
282
  mode=None,
262
- priority=priority,
263
283
  )
284
+ end = datetime.now()
285
+ output.execution_time = (end - start).total_seconds()
286
+ return output
264
287
 
265
288
  async def is_question(
266
289
  self,
@@ -295,7 +318,8 @@ class AsyncTheTool:
295
318
  - analysis (str | None): Detailed reasoning if with_analysis enabled
296
319
  - errors (list(str) | None): Errors occured during tool call
297
320
  """
298
- return await self._operator.run(
321
+ start = datetime.now()
322
+ output = await self._operator.run(
299
323
  # User parameters
300
324
  text=text,
301
325
  with_analysis=with_analysis,
@@ -305,13 +329,16 @@ class AsyncTheTool:
305
329
  top_logprobs=top_logprobs,
306
330
  validator=validator,
307
331
  max_validation_retries=max_validation_retries,
332
+ priority=priority,
308
333
  # Internal parameters
309
334
  prompt_file="is_question.yaml",
310
335
  output_model=Models.BoolOutput,
311
336
  mode=None,
312
337
  output_lang=None,
313
- priority=priority,
314
338
  )
339
+ end = datetime.now()
340
+ output.execution_time = (end - start).total_seconds()
341
+ return output
315
342
 
316
343
  async def text_to_question(
317
344
  self,
@@ -348,7 +375,8 @@ class AsyncTheTool:
348
375
  - analysis (str | None): Detailed reasoning if with_analysis enabled
349
376
  - errors (list(str) | None): Errors occured during tool call
350
377
  """
351
- return await self._operator.run(
378
+ start = datetime.now()
379
+ output = await self._operator.run(
352
380
  # User parameters
353
381
  text=text,
354
382
  with_analysis=with_analysis,
@@ -359,12 +387,15 @@ class AsyncTheTool:
359
387
  top_logprobs=top_logprobs,
360
388
  validator=validator,
361
389
  max_validation_retries=max_validation_retries,
390
+ priority=priority,
362
391
  # Internal parameters
363
392
  prompt_file="text_to_question.yaml",
364
393
  output_model=Models.StrOutput,
365
394
  mode=None,
366
- priority=priority,
367
395
  )
396
+ end = datetime.now()
397
+ output.execution_time = (end - start).total_seconds()
398
+ return output
368
399
 
369
400
  async def merge_questions(
370
401
  self,
@@ -403,10 +434,11 @@ class AsyncTheTool:
403
434
  - analysis (str | None): Detailed reasoning if with_analysis enabled
404
435
  - errors (list(str) | None): Errors occured during tool call
405
436
  """
406
- text = ", ".join(text)
407
- return await self._operator.run(
437
+ start = datetime.now()
438
+ text_combined = ", ".join(text)
439
+ output = await self._operator.run(
408
440
  # User parameters
409
- text=text,
441
+ text=text_combined,
410
442
  with_analysis=with_analysis,
411
443
  output_lang=output_lang,
412
444
  user_prompt=user_prompt,
@@ -415,12 +447,15 @@ class AsyncTheTool:
415
447
  top_logprobs=top_logprobs,
416
448
  validator=validator,
417
449
  max_validation_retries=max_validation_retries,
450
+ priority=priority,
418
451
  # Internal parameters
419
452
  prompt_file="merge_questions.yaml",
420
453
  output_model=Models.StrOutput,
421
454
  mode=mode,
422
- priority=priority,
423
455
  )
456
+ end = datetime.now()
457
+ output.execution_time = (end - start).total_seconds()
458
+ return output
424
459
 
425
460
  async def rewrite(
426
461
  self,
@@ -459,7 +494,8 @@ class AsyncTheTool:
459
494
  - analysis (str | None): Detailed reasoning if with_analysis enabled
460
495
  - errors (list(str) | None): Errors occured during tool call
461
496
  """
462
- return await self._operator.run(
497
+ start = datetime.now()
498
+ output = await self._operator.run(
463
499
  # User parameters
464
500
  text=text,
465
501
  with_analysis=with_analysis,
@@ -470,12 +506,15 @@ class AsyncTheTool:
470
506
  top_logprobs=top_logprobs,
471
507
  validator=validator,
472
508
  max_validation_retries=max_validation_retries,
509
+ priority=priority,
473
510
  # Internal parameters
474
511
  prompt_file="rewrite.yaml",
475
512
  output_model=Models.StrOutput,
476
513
  mode=mode,
477
- priority=priority,
478
514
  )
515
+ end = datetime.now()
516
+ output.execution_time = (end - start).total_seconds()
517
+ return output
479
518
 
480
519
  async def subject_to_question(
481
520
  self,
@@ -514,7 +553,8 @@ class AsyncTheTool:
514
553
  - analysis (str | None): Detailed reasoning if with_analysis enabled
515
554
  - errors (list(str) | None): Errors occured during tool call
516
555
  """
517
- return await self._operator.run(
556
+ start = datetime.now()
557
+ output = await self._operator.run(
518
558
  # User parameters
519
559
  text=text,
520
560
  number_of_questions=number_of_questions,
@@ -526,12 +566,15 @@ class AsyncTheTool:
526
566
  top_logprobs=top_logprobs,
527
567
  validator=validator,
528
568
  max_validation_retries=max_validation_retries,
569
+ priority=priority,
529
570
  # Internal parameters
530
571
  prompt_file="subject_to_question.yaml",
531
572
  output_model=Models.ReasonListStrOutput,
532
573
  mode=None,
533
- priority=priority,
534
574
  )
575
+ end = datetime.now()
576
+ output.execution_time = (end - start).total_seconds()
577
+ return output
535
578
 
536
579
  async def summarize(
537
580
  self,
@@ -568,7 +611,8 @@ class AsyncTheTool:
568
611
  - analysis (str | None): Detailed reasoning if with_analysis enabled
569
612
  - errors (list(str) | None): Errors occured during tool call
570
613
  """
571
- return await self._operator.run(
614
+ start = datetime.now()
615
+ output = await self._operator.run(
572
616
  # User parameters
573
617
  text=text,
574
618
  with_analysis=with_analysis,
@@ -579,12 +623,15 @@ class AsyncTheTool:
579
623
  top_logprobs=top_logprobs,
580
624
  validator=validator,
581
625
  max_validation_retries=max_validation_retries,
626
+ priority=priority,
582
627
  # Internal parameters
583
628
  prompt_file="summarize.yaml",
584
629
  output_model=Models.StrOutput,
585
630
  mode=None,
586
- priority=priority,
587
631
  )
632
+ end = datetime.now()
633
+ output.execution_time = (end - start).total_seconds()
634
+ return output
588
635
 
589
636
  async def translate(
590
637
  self,
@@ -621,7 +668,8 @@ class AsyncTheTool:
621
668
  - analysis (str | None): Detailed reasoning if with_analysis enabled
622
669
  - errors (list(str) | None): Errors occured during tool call
623
670
  """
624
- return await self._operator.run(
671
+ start = datetime.now()
672
+ output = await self._operator.run(
625
673
  # User parameters
626
674
  text=text,
627
675
  target_language=target_language,
@@ -632,13 +680,16 @@ class AsyncTheTool:
632
680
  top_logprobs=top_logprobs,
633
681
  validator=validator,
634
682
  max_validation_retries=max_validation_retries,
683
+ priority=priority,
635
684
  # Internal parameters
636
685
  prompt_file="translate.yaml",
637
686
  output_model=Models.StrOutput,
638
687
  mode=None,
639
688
  output_lang=None,
640
- priority=priority,
641
689
  )
690
+ end = datetime.now()
691
+ output.execution_time = (end - start).total_seconds()
692
+ return output
642
693
 
643
694
  async def detect_entity(
644
695
  self,
@@ -675,7 +726,8 @@ class AsyncTheTool:
675
726
  - analysis (str | None): Detailed reasoning if with_analysis enabled
676
727
  - errors (list(str) | None): Errors occured during tool call
677
728
  """
678
- return await self._operator.run(
729
+ start = datetime.now()
730
+ output = await self._operator.run(
679
731
  # User parameters
680
732
  text=text,
681
733
  with_analysis=with_analysis,
@@ -686,12 +738,15 @@ class AsyncTheTool:
686
738
  top_logprobs=top_logprobs,
687
739
  validator=validator,
688
740
  max_validation_retries=max_validation_retries,
741
+ priority=priority,
689
742
  # Internal parameters
690
743
  prompt_file="detect_entity.yaml",
691
744
  output_model=Models.EntityDetectorOutput,
692
745
  mode=None,
693
- priority=priority,
694
746
  )
747
+ end = datetime.now()
748
+ output.execution_time = (end - start).total_seconds()
749
+ return output
695
750
 
696
751
  async def run_custom(
697
752
  self,
@@ -725,7 +780,8 @@ class AsyncTheTool:
725
780
  - analysis (str | None): Detailed reasoning if with_analysis enabled
726
781
  - errors (list(str) | None): Errors occured during tool call
727
782
  """
728
- return await self._operator.run(
783
+ start = datetime.now()
784
+ output = await self._operator.run(
729
785
  # User paramaeters
730
786
  text=prompt,
731
787
  output_model=output_model,
@@ -736,10 +792,13 @@ class AsyncTheTool:
736
792
  top_logprobs=top_logprobs,
737
793
  validator=validator,
738
794
  max_validation_retries=max_validation_retries,
795
+ priority=priority,
739
796
  # Internal parameters
740
797
  prompt_file="run_custom.yaml",
741
798
  user_prompt=None,
742
799
  with_analysis=False,
743
800
  mode=None,
744
- priority=priority,
745
801
  )
802
+ end = datetime.now()
803
+ output.execution_time = (end - start).total_seconds()
804
+ return output
@@ -190,6 +190,8 @@ class AsyncOperator:
190
190
  if with_analysis:
191
191
  output.analysis = analysis
192
192
 
193
+ output.process = prompt_file[:-5]
194
+
193
195
  return output
194
196
 
195
197
  except Exception as e:
@@ -1,3 +1,4 @@
1
+ from datetime import datetime
1
2
  from typing import Type, Any, Literal
2
3
 
3
4
  from pydantic import BaseModel, Field, create_model
@@ -7,10 +8,13 @@ class ToolOutput(BaseModel):
7
8
  result: Any = None
8
9
  analysis: str = ""
9
10
  logprobs: list[dict[str, Any]] = []
11
+ process: str = ""
12
+ processed_at: datetime = datetime.now()
13
+ execution_time: datetime = None
10
14
  errors: list[str] = []
11
15
 
12
16
  def __repr__(self) -> str:
13
- return f"ToolOutput(result_type='{type(self.result)}', result='{self.result}', analysis='{self.analysis}', logprobs='{self.logprobs}', errors='{self.errors}'"
17
+ return f"ToolOutput(process='{self.process}', result_type='{type(self.result)}', result='{self.result}', analysis='{self.analysis}', logprobs='{self.logprobs}', errors='{self.errors}', processed_at='{self.processed_at}', execution_time='{self.execution_time}'"
14
18
 
15
19
 
16
20
  class StrOutput(BaseModel):
@@ -53,7 +57,7 @@ class Node(BaseModel):
53
57
  class CategoryTree:
54
58
  def __init__(self, tree_name):
55
59
  self.root = Node(node_id=0, name=tree_name, level=0, parent_id=None)
56
- self.node_list: list[Node] = [self.root]
60
+ self.all_nodes: list[Node] = [self.root]
57
61
  self.new_id = 1
58
62
 
59
63
  def add_node(
@@ -85,11 +89,14 @@ class CategoryTree:
85
89
  if description is not None:
86
90
  node_data["description"] = description
87
91
 
88
- self.node_list.append(Node(**node_data))
92
+ self.all_nodes.append(Node(**node_data))
89
93
  self.new_id += 1
90
94
 
91
95
  def get_nodes(self) -> list[Node]:
92
- return self.node_list
96
+ return self.all_nodes
97
+
98
+ def get_level_count(self) -> int:
99
+ return max([item.level for item in self.all_nodes])
93
100
 
94
101
  def find_node(self, identifier: int | str) -> Node | None:
95
102
  if isinstance(identifier, str):
@@ -106,11 +113,9 @@ class CategoryTree:
106
113
  return None
107
114
 
108
115
  def find_children(self, parent_node: Node) -> list[Node] | None:
109
- children = []
110
- for node in self.get_nodes():
111
- if parent_node.node_id == node.parent_id:
112
- children.append(node)
113
-
116
+ children = [
117
+ node for node in self.get_nodes() if parent_node.node_id == node.parent_id
118
+ ]
114
119
  return children if children else None
115
120
 
116
121
  def remove_node(self, identifier: int | str) -> None:
@@ -122,14 +127,14 @@ class CategoryTree:
122
127
 
123
128
  # Ending condition
124
129
  if children is None:
125
- self.node_list.remove(node)
130
+ self.all_nodes.remove(node)
126
131
  return
127
132
 
128
133
  for child in children:
129
134
  self.remove_node(child.name)
130
135
 
131
136
  # Remove the node from tree
132
- self.node_list.remove(node)
137
+ self.all_nodes.remove(node)
133
138
  else:
134
139
  raise ValueError(f"Node with identifier: '{identifier}' not found.")
135
140
 
@@ -137,7 +142,7 @@ class CategoryTree:
137
142
  def build_dict(node: Node) -> dict:
138
143
  children = [
139
144
  build_dict(child)
140
- for child in self.node_list
145
+ for child in self.all_nodes
141
146
  if child.parent_id == node.node_id
142
147
  ]
143
148
  return {
@@ -150,9 +155,6 @@ class CategoryTree:
150
155
 
151
156
  return {"category_tree": build_dict(self.root)["children"]}
152
157
 
153
- def level_count(self) -> int:
154
- return max([item.level for item in self.node_list])
155
-
156
158
 
157
159
  # This function is needed to create CategorizerOutput with dynamic categories
158
160
  def create_dynamic_model(allowed_values: list[str]) -> Type[BaseModel]:
@@ -174,7 +176,7 @@ def create_dynamic_model(allowed_values: list[str]) -> Type[BaseModel]:
174
176
 
175
177
  class Entity(BaseModel):
176
178
  text: str = Field(description="The exact text of the entity")
177
- type: str = Field(description="The type of the entity")
179
+ entity_type: str = Field(description="The type of the entity")
178
180
 
179
181
 
180
182
  class EntityDetectorOutput(BaseModel):
@@ -191,6 +191,8 @@ class Operator:
191
191
  if with_analysis:
192
192
  output.analysis = analysis
193
193
 
194
+ output.process = prompt_file[:-5]
195
+
194
196
  return output
195
197
 
196
198
  except Exception as e:
@@ -1,3 +1,4 @@
1
+ from datetime import datetime
1
2
  from typing import Literal, Any
2
3
  from collections.abc import Callable
3
4
 
@@ -61,10 +62,12 @@ class TheTool:
61
62
  - analysis (str | None): Detailed reasoning if with_analysis enabled
62
63
  - errors (list(str) | None): Errors occured during tool call
63
64
  """
65
+ start = datetime.now()
66
+
64
67
  if mode == "category_tree":
65
68
  # Initializations
66
69
  output = Models.ToolOutput()
67
- levels = categories.level_count()
70
+ levels = categories.get_level_count()
68
71
  parent_id = 0
69
72
  final_output = []
70
73
 
@@ -78,6 +81,8 @@ class TheTool:
78
81
  output.errors.append(
79
82
  f"No categories found for parent_id {parent_id} in the tree"
80
83
  )
84
+ end = datetime.now()
85
+ output.execution_time = (end - start).total_seconds()
81
86
  return output
82
87
 
83
88
  # Extract category names and descriptions
@@ -100,6 +105,7 @@ class TheTool:
100
105
  mode=mode,
101
106
  validator=validator,
102
107
  max_validation_retries=max_validation_retries,
108
+ priority=priority,
103
109
  # Internal parameters
104
110
  prompt_file="categorize.yaml",
105
111
  output_model=Models.create_dynamic_model(category_names),
@@ -109,6 +115,8 @@ class TheTool:
109
115
  # Check for errors from operator
110
116
  if level_output.errors:
111
117
  output.errors.extend(level_output.errors)
118
+ end = datetime.now()
119
+ output.execution_time = (end - start).total_seconds()
112
120
  return output
113
121
 
114
122
  # Get the chosen category
@@ -120,20 +128,25 @@ class TheTool:
120
128
  output.errors.append(
121
129
  f"Category '{chosen_category}' not found in tree after selection"
122
130
  )
131
+ end = datetime.now()
132
+ output.execution_time = (end - start).total_seconds()
123
133
  return output
124
134
 
125
135
  parent_id = parent_node.node_id
126
136
  final_output.append(parent_node.name)
127
137
 
128
- # Copy analysis/logprobs from the last level's output
138
+ # Copy analysis/logprobs/process from the last level's output
129
139
  output.analysis = level_output.analysis
130
140
  output.logprobs = level_output.logprobs
141
+ output.process = level_output.process
131
142
 
132
143
  output.result = final_output
144
+ end = datetime.now()
145
+ output.execution_time = (end - start).total_seconds()
133
146
  return output
134
147
 
135
148
  else:
136
- return self._operator.run(
149
+ output = self._operator.run(
137
150
  # User parameters
138
151
  text=text,
139
152
  category_list=categories,
@@ -145,11 +158,15 @@ class TheTool:
145
158
  mode=mode,
146
159
  validator=validator,
147
160
  max_validation_retries=max_validation_retries,
161
+ priority=priority,
148
162
  # Internal parameters
149
163
  prompt_file="categorize.yaml",
150
164
  output_model=Models.create_dynamic_model(categories),
151
165
  output_lang=None,
152
166
  )
167
+ end = datetime.now()
168
+ output.execution_time = (end - start).total_seconds()
169
+ return output
153
170
 
154
171
  def extract_keywords(
155
172
  self,
@@ -188,7 +205,8 @@ class TheTool:
188
205
  - analysis (str | None): Detailed reasoning if with_analysis enabled
189
206
  - errors (list(str) | None): Errors occured during tool call
190
207
  """
191
- return self._operator.run(
208
+ start = datetime.now()
209
+ output = self._operator.run(
192
210
  # User parameters
193
211
  text=text,
194
212
  with_analysis=with_analysis,
@@ -201,11 +219,14 @@ class TheTool:
201
219
  number_of_keywords=number_of_keywords,
202
220
  validator=validator,
203
221
  max_validation_retries=max_validation_retries,
222
+ priority=priority,
204
223
  # Internal parameters
205
224
  prompt_file="extract_keywords.yaml",
206
225
  output_model=Models.ListStrOutput,
207
- priority=priority,
208
226
  )
227
+ end = datetime.now()
228
+ output.execution_time = (end - start).total_seconds()
229
+ return output
209
230
 
210
231
  def extract_entities(
211
232
  self,
@@ -242,7 +263,8 @@ class TheTool:
242
263
  - analysis (str | None): Detailed reasoning if with_analysis enabled
243
264
  - errors (list(str) | None): Errors occured during tool call
244
265
  """
245
- return self._operator.run(
266
+ start = datetime.now()
267
+ output = self._operator.run(
246
268
  # User parameters
247
269
  text=text,
248
270
  with_analysis=with_analysis,
@@ -253,12 +275,15 @@ class TheTool:
253
275
  top_logprobs=top_logprobs,
254
276
  validator=validator,
255
277
  max_validation_retries=max_validation_retries,
278
+ priority=priority,
256
279
  # Internal parameters
257
280
  prompt_file="extract_entities.yaml",
258
281
  output_model=Models.ListDictStrStrOutput,
259
282
  mode=None,
260
- priority=priority,
261
283
  )
284
+ end = datetime.now()
285
+ output.execution_time = (end - start).total_seconds()
286
+ return output
262
287
 
263
288
  def is_question(
264
289
  self,
@@ -293,7 +318,8 @@ class TheTool:
293
318
  - analysis (str | None): Detailed reasoning if with_analysis enabled
294
319
  - errors (list(str) | None): Errors occured during tool call
295
320
  """
296
- return self._operator.run(
321
+ start = datetime.now()
322
+ output = self._operator.run(
297
323
  # User parameters
298
324
  text=text,
299
325
  with_analysis=with_analysis,
@@ -303,13 +329,16 @@ class TheTool:
303
329
  top_logprobs=top_logprobs,
304
330
  validator=validator,
305
331
  max_validation_retries=max_validation_retries,
332
+ priority=priority,
306
333
  # Internal parameters
307
334
  prompt_file="is_question.yaml",
308
335
  output_model=Models.BoolOutput,
309
336
  mode=None,
310
337
  output_lang=None,
311
- priority=priority,
312
338
  )
339
+ end = datetime.now()
340
+ output.execution_time = (end - start).total_seconds()
341
+ return output
313
342
 
314
343
  def text_to_question(
315
344
  self,
@@ -346,7 +375,8 @@ class TheTool:
346
375
  - analysis (str | None): Detailed reasoning if with_analysis enabled
347
376
  - errors (list(str) | None): Errors occured during tool call
348
377
  """
349
- return self._operator.run(
378
+ start = datetime.now()
379
+ output = self._operator.run(
350
380
  # User parameters
351
381
  text=text,
352
382
  with_analysis=with_analysis,
@@ -357,12 +387,15 @@ class TheTool:
357
387
  top_logprobs=top_logprobs,
358
388
  validator=validator,
359
389
  max_validation_retries=max_validation_retries,
390
+ priority=priority,
360
391
  # Internal parameters
361
392
  prompt_file="text_to_question.yaml",
362
393
  output_model=Models.StrOutput,
363
394
  mode=None,
364
- priority=priority,
365
395
  )
396
+ end = datetime.now()
397
+ output.execution_time = (end - start).total_seconds()
398
+ return output
366
399
 
367
400
  def merge_questions(
368
401
  self,
@@ -401,8 +434,9 @@ class TheTool:
401
434
  - analysis (str | None): Detailed reasoning if with_analysis enabled
402
435
  - errors (list(str) | None): Errors occured during tool call
403
436
  """
437
+ start = datetime.now()
404
438
  text = ", ".join(text)
405
- return self._operator.run(
439
+ output = self._operator.run(
406
440
  # User parameters
407
441
  text=text,
408
442
  with_analysis=with_analysis,
@@ -413,12 +447,15 @@ class TheTool:
413
447
  top_logprobs=top_logprobs,
414
448
  validator=validator,
415
449
  max_validation_retries=max_validation_retries,
450
+ priority=priority,
416
451
  # Internal parameters
417
452
  prompt_file="merge_questions.yaml",
418
453
  output_model=Models.StrOutput,
419
454
  mode=mode,
420
- priority=priority,
421
455
  )
456
+ end = datetime.now()
457
+ output.execution_time = (end - start).total_seconds()
458
+ return output
422
459
 
423
460
  def rewrite(
424
461
  self,
@@ -457,7 +494,8 @@ class TheTool:
457
494
  - analysis (str | None): Detailed reasoning if with_analysis enabled
458
495
  - errors (list(str) | None): Errors occured during tool call
459
496
  """
460
- return self._operator.run(
497
+ start = datetime.now()
498
+ output = self._operator.run(
461
499
  # User parameters
462
500
  text=text,
463
501
  with_analysis=with_analysis,
@@ -468,12 +506,15 @@ class TheTool:
468
506
  top_logprobs=top_logprobs,
469
507
  validator=validator,
470
508
  max_validation_retries=max_validation_retries,
509
+ priority=priority,
471
510
  # Internal parameters
472
511
  prompt_file="rewrite.yaml",
473
512
  output_model=Models.StrOutput,
474
513
  mode=mode,
475
- priority=priority,
476
514
  )
515
+ end = datetime.now()
516
+ output.execution_time = (end - start).total_seconds()
517
+ return output
477
518
 
478
519
  def subject_to_question(
479
520
  self,
@@ -512,7 +553,8 @@ class TheTool:
512
553
  - analysis (str | None): Detailed reasoning if with_analysis enabled
513
554
  - errors (list(str) | None): Errors occured during tool call
514
555
  """
515
- return self._operator.run(
556
+ start = datetime.now()
557
+ output = self._operator.run(
516
558
  # User parameters
517
559
  text=text,
518
560
  number_of_questions=number_of_questions,
@@ -524,12 +566,15 @@ class TheTool:
524
566
  top_logprobs=top_logprobs,
525
567
  validator=validator,
526
568
  max_validation_retries=max_validation_retries,
569
+ priority=priority,
527
570
  # Internal parameters
528
571
  prompt_file="subject_to_question.yaml",
529
572
  output_model=Models.ReasonListStrOutput,
530
573
  mode=None,
531
- priority=priority,
532
574
  )
575
+ end = datetime.now()
576
+ output.execution_time = (end - start).total_seconds()
577
+ return output
533
578
 
534
579
  def summarize(
535
580
  self,
@@ -566,7 +611,8 @@ class TheTool:
566
611
  - analysis (str | None): Detailed reasoning if with_analysis enabled
567
612
  - errors (list(str) | None): Errors occured during tool call
568
613
  """
569
- return self._operator.run(
614
+ start = datetime.now()
615
+ output = self._operator.run(
570
616
  # User parameters
571
617
  text=text,
572
618
  with_analysis=with_analysis,
@@ -577,12 +623,15 @@ class TheTool:
577
623
  top_logprobs=top_logprobs,
578
624
  validator=validator,
579
625
  max_validation_retries=max_validation_retries,
626
+ priority=priority,
580
627
  # Internal parameters
581
628
  prompt_file="summarize.yaml",
582
629
  output_model=Models.StrOutput,
583
630
  mode=None,
584
- priority=priority,
585
631
  )
632
+ end = datetime.now()
633
+ output.execution_time = (end - start).total_seconds()
634
+ return output
586
635
 
587
636
  def translate(
588
637
  self,
@@ -619,7 +668,8 @@ class TheTool:
619
668
  - analysis (str | None): Detailed reasoning if with_analysis enabled
620
669
  - errors (list(str) | None): Errors occured during tool call
621
670
  """
622
- return self._operator.run(
671
+ start = datetime.now()
672
+ output = self._operator.run(
623
673
  # User parameters
624
674
  text=text,
625
675
  target_language=target_language,
@@ -630,13 +680,16 @@ class TheTool:
630
680
  top_logprobs=top_logprobs,
631
681
  validator=validator,
632
682
  max_validation_retries=max_validation_retries,
683
+ priority=priority,
633
684
  # Internal parameters
634
685
  prompt_file="translate.yaml",
635
686
  output_model=Models.StrOutput,
636
687
  mode=None,
637
688
  output_lang=None,
638
- priority=priority,
639
689
  )
690
+ end = datetime.now()
691
+ output.execution_time = (end - start).total_seconds()
692
+ return output
640
693
 
641
694
  def detect_entity(
642
695
  self,
@@ -673,7 +726,8 @@ class TheTool:
673
726
  - analysis (str | None): Detailed reasoning if with_analysis enabled
674
727
  - errors (list(str) | None): Errors occured during tool call
675
728
  """
676
- return self._operator.run(
729
+ start = datetime.now()
730
+ output = self._operator.run(
677
731
  # User parameters
678
732
  text=text,
679
733
  with_analysis=with_analysis,
@@ -684,12 +738,15 @@ class TheTool:
684
738
  top_logprobs=top_logprobs,
685
739
  validator=validator,
686
740
  max_validation_retries=max_validation_retries,
741
+ priority=priority,
687
742
  # Internal parameters
688
743
  prompt_file="detect_entity.yaml",
689
744
  output_model=Models.EntityDetectorOutput,
690
745
  mode=None,
691
- priority=priority,
692
746
  )
747
+ end = datetime.now()
748
+ output.execution_time = (end - start).total_seconds()
749
+ return output
693
750
 
694
751
  def run_custom(
695
752
  self,
@@ -723,7 +780,8 @@ class TheTool:
723
780
  - analysis (str | None): Detailed reasoning if with_analysis enabled
724
781
  - errors (list(str) | None): Errors occured during tool call
725
782
  """
726
- return self._operator.run(
783
+ start = datetime.now()
784
+ output = self._operator.run(
727
785
  # User paramaeters
728
786
  text=prompt,
729
787
  output_model=output_model,
@@ -734,10 +792,13 @@ class TheTool:
734
792
  top_logprobs=top_logprobs,
735
793
  validator=validator,
736
794
  max_validation_retries=max_validation_retries,
795
+ priority=priority,
737
796
  # Internal parameters
738
797
  prompt_file="run_custom.yaml",
739
798
  user_prompt=None,
740
799
  with_analysis=False,
741
800
  mode=None,
742
- priority=priority,
743
801
  )
802
+ end = datetime.now()
803
+ output.execution_time = (end - start).total_seconds()
804
+ return output