hamtaa-texttools 1.1.16__py3-none-any.whl → 1.1.17__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,8 +1,8 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hamtaa-texttools
3
- Version: 1.1.16
3
+ Version: 1.1.17
4
4
  Summary: A high-level NLP toolkit built on top of modern LLMs.
5
- Author-email: Tohidi <the.mohammad.tohidi@gmail.com>, Montazer <montazerh82@gmail.com>, Givechi <mohamad.m.givechi@gmail.com>, MoosaviNejad <erfanmoosavi84@gmail.com>
5
+ Author-email: Tohidi <the.mohammad.tohidi@gmail.com>, Montazer <montazerh82@gmail.com>, Givechi <mohamad.m.givechi@gmail.com>, MoosaviNejad <erfanmoosavi84@gmail.com>, Zareshahi <a.zareshahi1377@gmail.com>
6
6
  License: MIT License
7
7
 
8
8
  Copyright (c) 2025 Hamtaa
@@ -60,6 +60,7 @@ Each tool is designed to work with structured outputs (JSON / Pydantic).
60
60
  - **`subject_to_question()`** - Generates questions about a specific subject
61
61
  - **`summarize()`** - Text summarization
62
62
  - **`translate()`** - Text translation between languages
63
+ - **`propositionize()`** - Convert text to atomic independence meaningful sentences
63
64
  - **`run_custom()`** - Allows users to define a custom tool with an arbitrary BaseModel
64
65
 
65
66
  ---
@@ -1,4 +1,4 @@
1
- hamtaa_texttools-1.1.16.dist-info/licenses/LICENSE,sha256=Hb2YOBKy2MJQLnyLrX37B4ZVuac8eaIcE71SvVIMOLg,1082
1
+ hamtaa_texttools-1.1.17.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
@@ -11,21 +11,22 @@ texttools/prompts/extract_entities.yaml,sha256=KiKjeDpHaeh3JVtZ6q1pa3k4DYucUIU9W
11
11
  texttools/prompts/extract_keywords.yaml,sha256=Vj4Tt3vT6LtpOo_iBZPo9oWI50oVdPGXe5i8yDR8ex4,3177
12
12
  texttools/prompts/is_question.yaml,sha256=d0-vKRbXWkxvO64ikvxRjEmpAXGpCYIPGhgexvPPjws,471
13
13
  texttools/prompts/merge_questions.yaml,sha256=0J85GvTirZB4ELwH3sk8ub_WcqqpYf6PrMKr3djlZeo,1792
14
+ texttools/prompts/propositionize.yaml,sha256=ZEFkYy8qYpFK2oCmZ-i5M7nFtlQp_q8bKQZbFSuyE3c,792
14
15
  texttools/prompts/rewrite.yaml,sha256=LO7He_IA3MZKz8a-LxH9DHJpOjpYwaYN1pbjp1Y0tFo,5392
15
16
  texttools/prompts/run_custom.yaml,sha256=38OkCoVITbuuS9c08UZSP1jZW4WjSmRIi8fR0RAiPu4,108
16
17
  texttools/prompts/subject_to_question.yaml,sha256=C7x7rNNm6U_ZG9HOn6zuzYOtvJUZ2skuWbL1-aYdd3E,1147
17
18
  texttools/prompts/summarize.yaml,sha256=o6rxGPfWtZd61Duvm8NVvCJqfq73b-wAuMSKR6UYUqY,459
18
19
  texttools/prompts/text_to_question.yaml,sha256=UheKYpDn6iyKI8NxunHZtFpNyfCLZZe5cvkuXpurUJY,783
19
20
  texttools/prompts/translate.yaml,sha256=mGT2uBCei6uucWqVbs4silk-UV060v3G0jnt0P6sr50,634
20
- texttools/tools/async_tools.py,sha256=vNAg0gxwUZPsMS4q8JCv7RlYymS8l_5FsFI5adEYT7w,34376
21
- texttools/tools/sync_tools.py,sha256=hFifFa9YatvSeGif2E_bIG006eMdIBr6SV9HsZ_dAlg,34187
21
+ texttools/tools/async_tools.py,sha256=hbFAvBOJ8Pvocxr6cGS8WHFEYnRC6GhmVl_JxCloGhM,40163
22
+ texttools/tools/sync_tools.py,sha256=kUzU3lE5ZWeBNXvmQqqVC8HWr745eOui7oZlW3-7mJo,39964
22
23
  texttools/tools/internals/async_operator.py,sha256=1TMr8e1qbE9GSz8jl0q3MKdM8lIYE-1ZuSxHjYPqKHI,7198
23
24
  texttools/tools/internals/formatters.py,sha256=tACNLP6PeoqaRpNudVxBaHA25zyWqWYPZQuYysIu88g,941
24
- texttools/tools/internals/models.py,sha256=2QnvMiijuSqOqpCl026848rJy_pHNbRoDESlQvcdHlk,5839
25
+ texttools/tools/internals/models.py,sha256=lbhwH8FMwKkLnIOqu4jK3HNv4q_CrY9w3QQ_stlPs1Y,5961
25
26
  texttools/tools/internals/operator_utils.py,sha256=w1k0RJ_W_CRbVc_J2w337VuL-opHpHiCxfhEOwtyuOo,1856
26
27
  texttools/tools/internals/prompt_loader.py,sha256=4g6-U8kqrGN7VpNaRcrBcnF-h03PXjUDBP0lL0_4EZY,1953
27
28
  texttools/tools/internals/sync_operator.py,sha256=4-V__o55Q8w29lWxkhG4St-exZLZTfBbiW76knOXbc0,7106
28
- hamtaa_texttools-1.1.16.dist-info/METADATA,sha256=DL-cjlGMv7bft8QVd-pn5E_tNDuPgQHkTKGl4YTosGw,9555
29
- hamtaa_texttools-1.1.16.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
30
- hamtaa_texttools-1.1.16.dist-info/top_level.txt,sha256=5Mh0jIxxZ5rOXHGJ6Mp-JPKviywwN0MYuH0xk5bEWqE,10
31
- hamtaa_texttools-1.1.16.dist-info/RECORD,,
29
+ hamtaa_texttools-1.1.17.dist-info/METADATA,sha256=2h8GKwr3HKsaW10OKofe_JMZDD7Jas9cdvFFEwFCS_M,9680
30
+ hamtaa_texttools-1.1.17.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
31
+ hamtaa_texttools-1.1.17.dist-info/top_level.txt,sha256=5Mh0jIxxZ5rOXHGJ6Mp-JPKviywwN0MYuH0xk5bEWqE,10
32
+ hamtaa_texttools-1.1.17.dist-info/RECORD,,
@@ -0,0 +1,15 @@
1
+ main_template: |
2
+ You are an expert in breaking down text into atomic propositions in that language.
3
+ An atomic proposition is a single, self-contained fact that is concise, verifiable,
4
+ and does not rely on external context.
5
+ Each proposition must stand alone.
6
+ Rewrite sentences if needed to keep the context saved in each sentence.
7
+ Extract the atomic propositions of this text:
8
+ {input}
9
+
10
+ analyze_template: |
11
+ We want to analyze this text snippet and think about where we can split sentence to atomic meaningful propositions.
12
+ An atomic proposition is a single, self-contained fact that is concise,
13
+ verifiable, and does not rely on external context.
14
+ You just have to think around the possible propositions in the text and how a proposition can be made.
15
+ {input}
@@ -62,6 +62,9 @@ class AsyncTheTool:
62
62
  - result (str): The assigned category
63
63
  - logprobs (list | None): Probability data if logprobs enabled
64
64
  - analysis (str | None): Detailed reasoning if with_analysis enabled
65
+ - process (str | None): Description of the process used
66
+ - processed_at (datetime): Timestamp when the processing occurred
67
+ - execution_time (float): Time taken for execution in seconds (-1.0 if not measured)
65
68
  - errors (list(str) | None): Errors occured during tool call
66
69
  """
67
70
  start = datetime.now()
@@ -75,8 +78,8 @@ class AsyncTheTool:
75
78
 
76
79
  for _ in range(levels):
77
80
  # Get child nodes for current parent
78
- parent_node = categories.find_node(parent_id)
79
- children = categories.find_children(parent_node)
81
+ parent_node = categories.get_node(parent_id)
82
+ children = categories.get_children(parent_node)
80
83
 
81
84
  # Check if child nodes exist
82
85
  if not children:
@@ -124,7 +127,7 @@ class AsyncTheTool:
124
127
  chosen_category = level_output.result
125
128
 
126
129
  # Find the corresponding node
127
- parent_node = categories.find_node(chosen_category)
130
+ parent_node = categories.get_node(chosen_category)
128
131
  if parent_node is None:
129
132
  output.errors.append(
130
133
  f"Category '{chosen_category}' not found in tree after selection"
@@ -203,6 +206,9 @@ class AsyncTheTool:
203
206
  - result (list[str]): List of extracted keywords
204
207
  - logprobs (list | None): Probability data if logprobs enabled
205
208
  - analysis (str | None): Detailed reasoning if with_analysis enabled
209
+ - process (str | None): Description of the process used
210
+ - processed_at (datetime): Timestamp when the processing occurred
211
+ - execution_time (float): Time taken for execution in seconds (-1.0 if not measured)
206
212
  - errors (list(str) | None): Errors occured during tool call
207
213
  """
208
214
  start = datetime.now()
@@ -261,6 +267,9 @@ class AsyncTheTool:
261
267
  - result (list[dict]): List of entities with 'text' and 'type' keys
262
268
  - logprobs (list | None): Probability data if logprobs enabled
263
269
  - analysis (str | None): Detailed reasoning if with_analysis enabled
270
+ - process (str | None): Description of the process used
271
+ - processed_at (datetime): Timestamp when the processing occurred
272
+ - execution_time (float): Time taken for execution in seconds (-1.0 if not measured)
264
273
  - errors (list(str) | None): Errors occured during tool call
265
274
  """
266
275
  start = datetime.now()
@@ -316,6 +325,9 @@ class AsyncTheTool:
316
325
  - result (bool): True if text is a question, False otherwise
317
326
  - logprobs (list | None): Probability data if logprobs enabled
318
327
  - analysis (str | None): Detailed reasoning if with_analysis enabled
328
+ - process (str | None): Description of the process used
329
+ - processed_at (datetime): Timestamp when the processing occurred
330
+ - execution_time (float): Time taken for execution in seconds (-1.0 if not measured)
319
331
  - errors (list(str) | None): Errors occured during tool call
320
332
  """
321
333
  start = datetime.now()
@@ -373,6 +385,9 @@ class AsyncTheTool:
373
385
  - result (str): The generated question
374
386
  - logprobs (list | None): Probability data if logprobs enabled
375
387
  - analysis (str | None): Detailed reasoning if with_analysis enabled
388
+ - process (str | None): Description of the process used
389
+ - processed_at (datetime): Timestamp when the processing occurred
390
+ - execution_time (float): Time taken for execution in seconds (-1.0 if not measured)
376
391
  - errors (list(str) | None): Errors occured during tool call
377
392
  """
378
393
  start = datetime.now()
@@ -432,6 +447,9 @@ class AsyncTheTool:
432
447
  - result (str): The merged question
433
448
  - logprobs (list | None): Probability data if logprobs enabled
434
449
  - analysis (str | None): Detailed reasoning if with_analysis enabled
450
+ - process (str | None): Description of the process used
451
+ - processed_at (datetime): Timestamp when the processing occurred
452
+ - execution_time (float): Time taken for execution in seconds (-1.0 if not measured)
435
453
  - errors (list(str) | None): Errors occured during tool call
436
454
  """
437
455
  start = datetime.now()
@@ -492,6 +510,9 @@ class AsyncTheTool:
492
510
  - result (str): The rewritten text
493
511
  - logprobs (list | None): Probability data if logprobs enabled
494
512
  - analysis (str | None): Detailed reasoning if with_analysis enabled
513
+ - process (str | None): Description of the process used
514
+ - processed_at (datetime): Timestamp when the processing occurred
515
+ - execution_time (float): Time taken for execution in seconds (-1.0 if not measured)
495
516
  - errors (list(str) | None): Errors occured during tool call
496
517
  """
497
518
  start = datetime.now()
@@ -551,6 +572,9 @@ class AsyncTheTool:
551
572
  - result (list[str]): List of generated questions
552
573
  - logprobs (list | None): Probability data if logprobs enabled
553
574
  - analysis (str | None): Detailed reasoning if with_analysis enabled
575
+ - process (str | None): Description of the process used
576
+ - processed_at (datetime): Timestamp when the processing occurred
577
+ - execution_time (float): Time taken for execution in seconds (-1.0 if not measured)
554
578
  - errors (list(str) | None): Errors occured during tool call
555
579
  """
556
580
  start = datetime.now()
@@ -609,6 +633,9 @@ class AsyncTheTool:
609
633
  - result (str): The summary text
610
634
  - logprobs (list | None): Probability data if logprobs enabled
611
635
  - analysis (str | None): Detailed reasoning if with_analysis enabled
636
+ - process (str | None): Description of the process used
637
+ - processed_at (datetime): Timestamp when the processing occurred
638
+ - execution_time (float): Time taken for execution in seconds (-1.0 if not measured)
612
639
  - errors (list(str) | None): Errors occured during tool call
613
640
  """
614
641
  start = datetime.now()
@@ -666,6 +693,9 @@ class AsyncTheTool:
666
693
  - result (str): The translated text
667
694
  - logprobs (list | None): Probability data if logprobs enabled
668
695
  - analysis (str | None): Detailed reasoning if with_analysis enabled
696
+ - process (str | None): Description of the process used
697
+ - processed_at (datetime): Timestamp when the processing occurred
698
+ - execution_time (float): Time taken for execution in seconds (-1.0 if not measured)
669
699
  - errors (list(str) | None): Errors occured during tool call
670
700
  """
671
701
  start = datetime.now()
@@ -724,6 +754,9 @@ class AsyncTheTool:
724
754
  - result (list[Entity]): The entities
725
755
  - logprobs (list | None): Probability data if logprobs enabled
726
756
  - analysis (str | None): Detailed reasoning if with_analysis enabled
757
+ - process (str | None): Description of the process used
758
+ - processed_at (datetime): Timestamp when the processing occurred
759
+ - execution_time (float): Time taken for execution in seconds (-1.0 if not measured)
727
760
  - errors (list(str) | None): Errors occured during tool call
728
761
  """
729
762
  start = datetime.now()
@@ -748,6 +781,66 @@ class AsyncTheTool:
748
781
  output.execution_time = (end - start).total_seconds()
749
782
  return output
750
783
 
784
+ async def propositionize(
785
+ self,
786
+ text: str,
787
+ with_analysis: bool = False,
788
+ output_lang: str | None = None,
789
+ user_prompt: str | None = None,
790
+ temperature: float | None = 0.0,
791
+ logprobs: bool = False,
792
+ top_logprobs: int | None = None,
793
+ validator: Callable[[Any], bool] | None = None,
794
+ max_validation_retries: int | None = None,
795
+ priority: int | None = 0,
796
+ ) -> Models.ToolOutput:
797
+ """
798
+ Proposition input text to meaningful sentences.
799
+
800
+ Arguments:
801
+ text: The input text
802
+ with_analysis: Whether to include detailed reasoning analysis
803
+ output_lang: Language for the output summary
804
+ user_prompt: Additional instructions for summarization
805
+ temperature: Controls randomness (0.0 = deterministic, 1.0 = creative)
806
+ logprobs: Whether to return token probability information
807
+ top_logprobs: Number of top token alternatives to return if logprobs enabled
808
+ validator: Custom validation function to validate the output
809
+ max_validation_retries: Maximum number of retry attempts if validation fails
810
+ priority: Task execution priority (if enabled by vLLM and model)
811
+
812
+ Returns:
813
+ ToolOutput: Object containing:
814
+ - result (list[str]): The propositions
815
+ - logprobs (list | None): Probability data if logprobs enabled
816
+ - analysis (str | None): Detailed reasoning if with_analysis enabled
817
+ - process (str | None): Description of the process used
818
+ - processed_at (datetime): Timestamp when the processing occurred
819
+ - execution_time (float): Time taken for execution in seconds (-1.0 if not measured)
820
+ - errors (list(str) | None): Errors occured during tool call
821
+ """
822
+ start = datetime.now()
823
+ output = await self._operator.run(
824
+ # User parameters
825
+ text=text,
826
+ with_analysis=with_analysis,
827
+ output_lang=output_lang,
828
+ user_prompt=user_prompt,
829
+ temperature=temperature,
830
+ logprobs=logprobs,
831
+ top_logprobs=top_logprobs,
832
+ validator=validator,
833
+ max_validation_retries=max_validation_retries,
834
+ priority=priority,
835
+ # Internal parameters
836
+ prompt_file="propositionize.yaml",
837
+ output_model=Models.ListStrOutput,
838
+ mode=None,
839
+ )
840
+ end = datetime.now()
841
+ output.execution_time = (end - start).total_seconds()
842
+ return output
843
+
751
844
  async def run_custom(
752
845
  self,
753
846
  prompt: str,
@@ -778,6 +871,9 @@ class AsyncTheTool:
778
871
  - result (str): The translated text
779
872
  - logprobs (list | None): Probability data if logprobs enabled
780
873
  - analysis (str | None): Detailed reasoning if with_analysis enabled
874
+ - process (str | None): Description of the process used
875
+ - processed_at (datetime): Timestamp when the processing occurred
876
+ - execution_time (float): Time taken for execution in seconds (-1.0 if not measured)
781
877
  - errors (list(str) | None): Errors occured during tool call
782
878
  """
783
879
  start = datetime.now()
@@ -6,19 +6,24 @@ from pydantic import BaseModel, Field, create_model
6
6
 
7
7
  class ToolOutput(BaseModel):
8
8
  result: Any = None
9
- analysis: str = ""
10
9
  logprobs: list[dict[str, Any]] = []
10
+ analysis: str = ""
11
11
  process: str = ""
12
12
  processed_at: datetime = datetime.now()
13
13
  execution_time: float = -1.0
14
14
  errors: list[str] = []
15
15
 
16
16
  def __repr__(self) -> str:
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}'"
17
+ return f"""
18
+ ToolOutput(process='{self.process}', result_type='{type(self.result)}',
19
+ result='{self.result}', analysis='{self.analysis}',
20
+ logprobs='{self.logprobs}', errors='{self.errors}',
21
+ processed_at='{self.processed_at}', execution_time='{self.execution_time}'
22
+ """
18
23
 
19
24
 
20
25
  class StrOutput(BaseModel):
21
- result: str = Field(..., description="The output string")
26
+ result: str = Field(..., description="The output string", example="text")
22
27
 
23
28
 
24
29
  class BoolOutput(BaseModel):
@@ -37,13 +42,15 @@ class ListDictStrStrOutput(BaseModel):
37
42
  result: list[dict[str, str]] = Field(
38
43
  ...,
39
44
  description="List of dictionaries containing string key-value pairs",
40
- example=[{"text": "Mohammad", "type": "PER"}],
45
+ example=[{"text": "Mohammad", "type": "PER"}, {"text": "Iran", "type": "LOC"}],
41
46
  )
42
47
 
43
48
 
44
49
  class ReasonListStrOutput(BaseModel):
45
50
  reason: str = Field(..., description="Thinking process that led to the output")
46
- result: list[str] = Field(..., description="The output list of strings")
51
+ result: list[str] = Field(
52
+ ..., description="The output list of strings", example=["text_1", "text_2"]
53
+ )
47
54
 
48
55
 
49
56
  class Node(BaseModel):
@@ -51,14 +58,44 @@ class Node(BaseModel):
51
58
  name: str
52
59
  level: int
53
60
  parent_id: int | None
54
- description: str = "No description provided"
61
+ description: str
55
62
 
56
63
 
57
64
  class CategoryTree:
58
65
  def __init__(self, tree_name):
59
- self.root = Node(node_id=0, name=tree_name, level=0, parent_id=None)
60
- self.all_nodes: list[Node] = [self.root]
61
- self.new_id = 1
66
+ self._root = Node(
67
+ node_id=0, name=tree_name, level=0, parent_id=None, description="Root node"
68
+ )
69
+ self._all_nodes: list[Node] = [self._root]
70
+ self._new_id = 1
71
+
72
+ def get_all_nodes(self) -> list[Node]:
73
+ return self._all_nodes
74
+
75
+ def get_level_count(self) -> int:
76
+ return max([item.level for item in self._all_nodes])
77
+
78
+ def get_node(self, identifier: int | str) -> Node | None:
79
+ if isinstance(identifier, str):
80
+ for node in self.get_all_nodes():
81
+ if node.name == identifier:
82
+ return node
83
+ return None
84
+ elif isinstance(identifier, int):
85
+ for node in self.get_all_nodes():
86
+ if node.node_id == identifier:
87
+ return node
88
+ return None
89
+ else:
90
+ return None
91
+
92
+ def get_children(self, parent_node: Node) -> list[Node] | None:
93
+ children = [
94
+ node
95
+ for node in self.get_all_nodes()
96
+ if parent_node.node_id == node.parent_id
97
+ ]
98
+ return children if children else None
62
99
 
63
100
  def add_node(
64
101
  self,
@@ -66,12 +103,12 @@ class CategoryTree:
66
103
  parent_name: str | None = None,
67
104
  description: str | None = None,
68
105
  ) -> None:
69
- if self.find_node(node_name):
106
+ if self.get_node(node_name):
70
107
  raise ValueError(f"{node_name} has been chosen for another category before")
71
108
 
72
109
  if parent_name:
73
- parent_node = self.find_node(parent_name)
74
- if parent_node is None:
110
+ parent_node = self.get_node(parent_name)
111
+ if not parent_node:
75
112
  raise ValueError(f"Parent category '{parent_name}' not found")
76
113
  parent_id = parent_node.node_id
77
114
  level = parent_node.level + 1
@@ -80,61 +117,31 @@ class CategoryTree:
80
117
  parent_id = 0
81
118
 
82
119
  node_data = {
83
- "node_id": self.new_id,
120
+ "node_id": self._new_id,
84
121
  "name": node_name,
85
122
  "level": level,
86
123
  "parent_id": parent_id,
124
+ "description": description if description else "No description provided",
87
125
  }
88
126
 
89
- if description is not None:
90
- node_data["description"] = description
91
-
92
- self.all_nodes.append(Node(**node_data))
93
- self.new_id += 1
94
-
95
- def get_nodes(self) -> list[Node]:
96
- return self.all_nodes
97
-
98
- def get_level_count(self) -> int:
99
- return max([item.level for item in self.all_nodes])
100
-
101
- def find_node(self, identifier: int | str) -> Node | None:
102
- if isinstance(identifier, str):
103
- for node in self.get_nodes():
104
- if node.name == identifier:
105
- return node
106
- return None
107
- elif isinstance(identifier, int):
108
- for node in self.get_nodes():
109
- if node.node_id == identifier:
110
- return node
111
- return None
112
- else:
113
- return None
114
-
115
- def find_children(self, parent_node: Node) -> list[Node] | None:
116
- children = [
117
- node for node in self.get_nodes() if parent_node.node_id == node.parent_id
118
- ]
119
- return children if children else None
127
+ self._all_nodes.append(Node(**node_data))
128
+ self._new_id += 1
120
129
 
121
130
  def remove_node(self, identifier: int | str) -> None:
122
- node = self.find_node(identifier)
131
+ node = self.get_node(identifier)
123
132
 
124
- if node is not None:
133
+ if node:
125
134
  # Remove node's children recursively
126
- children = self.find_children(node)
135
+ children = self.get_children(node)
127
136
 
128
- # Ending condition
129
- if children is None:
130
- self.all_nodes.remove(node)
137
+ if not children:
138
+ self._all_nodes.remove(node)
131
139
  return
132
140
 
133
141
  for child in children:
134
142
  self.remove_node(child.name)
135
143
 
136
- # Remove the node from tree
137
- self.all_nodes.remove(node)
144
+ self._all_nodes.remove(node)
138
145
  else:
139
146
  raise ValueError(f"Node with identifier: '{identifier}' not found.")
140
147
 
@@ -142,7 +149,7 @@ class CategoryTree:
142
149
  def build_dict(node: Node) -> dict:
143
150
  children = [
144
151
  build_dict(child)
145
- for child in self.all_nodes
152
+ for child in self._all_nodes
146
153
  if child.parent_id == node.node_id
147
154
  ]
148
155
  return {
@@ -153,7 +160,7 @@ class CategoryTree:
153
160
  "children": children,
154
161
  }
155
162
 
156
- return {"category_tree": build_dict(self.root)["children"]}
163
+ return {"category_tree": build_dict(self._root)["children"]}
157
164
 
158
165
 
159
166
  # This function is needed to create CategorizerOutput with dynamic categories
@@ -60,7 +60,11 @@ class TheTool:
60
60
  - result (str): The assigned category
61
61
  - logprobs (list | None): Probability data if logprobs enabled
62
62
  - analysis (str | None): Detailed reasoning if with_analysis enabled
63
+ - process (str | None): Description of the process used
64
+ - processed_at (datetime): Timestamp when the processing occurred
65
+ - execution_time (float): Time taken for execution in seconds (-1.0 if not measured)
63
66
  - errors (list(str) | None): Errors occured during tool call
67
+
64
68
  """
65
69
  start = datetime.now()
66
70
 
@@ -73,8 +77,8 @@ class TheTool:
73
77
 
74
78
  for _ in range(levels):
75
79
  # Get child nodes for current parent
76
- parent_node = categories.find_node(parent_id)
77
- children = categories.find_children(parent_node)
80
+ parent_node = categories.get_node(parent_id)
81
+ children = categories.get_children(parent_node)
78
82
 
79
83
  # Check if child nodes exist
80
84
  if not children:
@@ -123,7 +127,7 @@ class TheTool:
123
127
  chosen_category = level_output.result
124
128
 
125
129
  # Find the corresponding node
126
- parent_node = categories.find_node(chosen_category)
130
+ parent_node = categories.get_node(chosen_category)
127
131
  if parent_node is None:
128
132
  output.errors.append(
129
133
  f"Category '{chosen_category}' not found in tree after selection"
@@ -203,6 +207,9 @@ class TheTool:
203
207
  - result (list[str]): List of extracted keywords
204
208
  - logprobs (list | None): Probability data if logprobs enabled
205
209
  - analysis (str | None): Detailed reasoning if with_analysis enabled
210
+ - process (str | None): Description of the process used
211
+ - processed_at (datetime): Timestamp when the processing occurred
212
+ - execution_time (float): Time taken for execution in seconds (-1.0 if not measured)
206
213
  - errors (list(str) | None): Errors occured during tool call
207
214
  """
208
215
  start = datetime.now()
@@ -261,6 +268,9 @@ class TheTool:
261
268
  - result (list[dict]): List of entities with 'text' and 'type' keys
262
269
  - logprobs (list | None): Probability data if logprobs enabled
263
270
  - analysis (str | None): Detailed reasoning if with_analysis enabled
271
+ - process (str | None): Description of the process used
272
+ - processed_at (datetime): Timestamp when the processing occurred
273
+ - execution_time (float): Time taken for execution in seconds (-1.0 if not measured)
264
274
  - errors (list(str) | None): Errors occured during tool call
265
275
  """
266
276
  start = datetime.now()
@@ -316,6 +326,9 @@ class TheTool:
316
326
  - result (bool): True if text is a question, False otherwise
317
327
  - logprobs (list | None): Probability data if logprobs enabled
318
328
  - analysis (str | None): Detailed reasoning if with_analysis enabled
329
+ - process (str | None): Description of the process used
330
+ - processed_at (datetime): Timestamp when the processing occurred
331
+ - execution_time (float): Time taken for execution in seconds (-1.0 if not measured)
319
332
  - errors (list(str) | None): Errors occured during tool call
320
333
  """
321
334
  start = datetime.now()
@@ -373,6 +386,9 @@ class TheTool:
373
386
  - result (str): The generated question
374
387
  - logprobs (list | None): Probability data if logprobs enabled
375
388
  - analysis (str | None): Detailed reasoning if with_analysis enabled
389
+ - process (str | None): Description of the process used
390
+ - processed_at (datetime): Timestamp when the processing occurred
391
+ - execution_time (float): Time taken for execution in seconds (-1.0 if not measured)
376
392
  - errors (list(str) | None): Errors occured during tool call
377
393
  """
378
394
  start = datetime.now()
@@ -432,6 +448,9 @@ class TheTool:
432
448
  - result (str): The merged question
433
449
  - logprobs (list | None): Probability data if logprobs enabled
434
450
  - analysis (str | None): Detailed reasoning if with_analysis enabled
451
+ - process (str | None): Description of the process used
452
+ - processed_at (datetime): Timestamp when the processing occurred
453
+ - execution_time (float): Time taken for execution in seconds (-1.0 if not measured)
435
454
  - errors (list(str) | None): Errors occured during tool call
436
455
  """
437
456
  start = datetime.now()
@@ -492,6 +511,9 @@ class TheTool:
492
511
  - result (str): The rewritten text
493
512
  - logprobs (list | None): Probability data if logprobs enabled
494
513
  - analysis (str | None): Detailed reasoning if with_analysis enabled
514
+ - process (str | None): Description of the process used
515
+ - processed_at (datetime): Timestamp when the processing occurred
516
+ - execution_time (float): Time taken for execution in seconds (-1.0 if not measured)
495
517
  - errors (list(str) | None): Errors occured during tool call
496
518
  """
497
519
  start = datetime.now()
@@ -551,6 +573,9 @@ class TheTool:
551
573
  - result (list[str]): List of generated questions
552
574
  - logprobs (list | None): Probability data if logprobs enabled
553
575
  - analysis (str | None): Detailed reasoning if with_analysis enabled
576
+ - process (str | None): Description of the process used
577
+ - processed_at (datetime): Timestamp when the processing occurred
578
+ - execution_time (float): Time taken for execution in seconds (-1.0 if not measured)
554
579
  - errors (list(str) | None): Errors occured during tool call
555
580
  """
556
581
  start = datetime.now()
@@ -609,6 +634,9 @@ class TheTool:
609
634
  - result (str): The summary text
610
635
  - logprobs (list | None): Probability data if logprobs enabled
611
636
  - analysis (str | None): Detailed reasoning if with_analysis enabled
637
+ - process (str | None): Description of the process used
638
+ - processed_at (datetime): Timestamp when the processing occurred
639
+ - execution_time (float): Time taken for execution in seconds (-1.0 if not measured)
612
640
  - errors (list(str) | None): Errors occured during tool call
613
641
  """
614
642
  start = datetime.now()
@@ -666,6 +694,9 @@ class TheTool:
666
694
  - result (str): The translated text
667
695
  - logprobs (list | None): Probability data if logprobs enabled
668
696
  - analysis (str | None): Detailed reasoning if with_analysis enabled
697
+ - process (str | None): Description of the process used
698
+ - processed_at (datetime): Timestamp when the processing occurred
699
+ - execution_time (float): Time taken for execution in seconds (-1.0 if not measured)
669
700
  - errors (list(str) | None): Errors occured during tool call
670
701
  """
671
702
  start = datetime.now()
@@ -724,6 +755,9 @@ class TheTool:
724
755
  - result (list[Entity]): The entities
725
756
  - logprobs (list | None): Probability data if logprobs enabled
726
757
  - analysis (str | None): Detailed reasoning if with_analysis enabled
758
+ - process (str | None): Description of the process used
759
+ - processed_at (datetime): Timestamp when the processing occurred
760
+ - execution_time (float): Time taken for execution in seconds (-1.0 if not measured)
727
761
  - errors (list(str) | None): Errors occured during tool call
728
762
  """
729
763
  start = datetime.now()
@@ -748,6 +782,66 @@ class TheTool:
748
782
  output.execution_time = (end - start).total_seconds()
749
783
  return output
750
784
 
785
+ def propositionize(
786
+ self,
787
+ text: str,
788
+ with_analysis: bool = False,
789
+ output_lang: str | None = None,
790
+ user_prompt: str | None = None,
791
+ temperature: float | None = 0.0,
792
+ logprobs: bool = False,
793
+ top_logprobs: int | None = None,
794
+ validator: Callable[[Any], bool] | None = None,
795
+ max_validation_retries: int | None = None,
796
+ priority: int | None = 0,
797
+ ) -> Models.ToolOutput:
798
+ """
799
+ Proposition input text to meaningful sentences.
800
+
801
+ Arguments:
802
+ text: The input text
803
+ with_analysis: Whether to include detailed reasoning analysis
804
+ output_lang: Language for the output summary
805
+ user_prompt: Additional instructions for summarization
806
+ temperature: Controls randomness (0.0 = deterministic, 1.0 = creative)
807
+ logprobs: Whether to return token probability information
808
+ top_logprobs: Number of top token alternatives to return if logprobs enabled
809
+ validator: Custom validation function to validate the output
810
+ max_validation_retries: Maximum number of retry attempts if validation fails
811
+ priority: Task execution priority (if enabled by vLLM and model)
812
+
813
+ Returns:
814
+ ToolOutput: Object containing:
815
+ - result (list[str]): The propositions
816
+ - logprobs (list | None): Probability data if logprobs enabled
817
+ - analysis (str | None): Detailed reasoning if with_analysis enabled
818
+ - process (str | None): Description of the process used
819
+ - processed_at (datetime): Timestamp when the processing occurred
820
+ - execution_time (float): Time taken for execution in seconds (-1.0 if not measured)
821
+ - errors (list(str) | None): Errors occured during tool call
822
+ """
823
+ start = datetime.now()
824
+ output = self._operator.run(
825
+ # User parameters
826
+ text=text,
827
+ with_analysis=with_analysis,
828
+ output_lang=output_lang,
829
+ user_prompt=user_prompt,
830
+ temperature=temperature,
831
+ logprobs=logprobs,
832
+ top_logprobs=top_logprobs,
833
+ validator=validator,
834
+ max_validation_retries=max_validation_retries,
835
+ priority=priority,
836
+ # Internal parameters
837
+ prompt_file="propositionize.yaml",
838
+ output_model=Models.ListStrOutput,
839
+ mode=None,
840
+ )
841
+ end = datetime.now()
842
+ output.execution_time = (end - start).total_seconds()
843
+ return output
844
+
751
845
  def run_custom(
752
846
  self,
753
847
  prompt: str,
@@ -778,6 +872,9 @@ class TheTool:
778
872
  - result (str): The translated text
779
873
  - logprobs (list | None): Probability data if logprobs enabled
780
874
  - analysis (str | None): Detailed reasoning if with_analysis enabled
875
+ - process (str | None): Description of the process used
876
+ - processed_at (datetime): Timestamp when the processing occurred
877
+ - execution_time (float): Time taken for execution in seconds (-1.0 if not measured)
781
878
  - errors (list(str) | None): Errors occured during tool call
782
879
  """
783
880
  start = datetime.now()