unique_toolkit 0.8.4__py3-none-any.whl → 0.8.5__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.
- unique_toolkit/app/schemas.py +3 -0
- unique_toolkit/language_model/schemas.py +18 -0
- unique_toolkit/reference_manager/reference_manager.py +72 -0
- unique_toolkit/tools/agent_chunks_handler.py +62 -0
- unique_toolkit/tools/config.py +108 -0
- unique_toolkit/tools/{tool_factory.py → factory.py} +15 -5
- unique_toolkit/tools/schemas.py +138 -0
- unique_toolkit/tools/test/test_tool_progress_reporter.py +204 -0
- unique_toolkit/tools/tool.py +168 -0
- unique_toolkit/tools/tool_manager.py +242 -0
- unique_toolkit/tools/tool_progress_reporter.py +4 -11
- unique_toolkit/tools/utils/execution/execution.py +282 -0
- unique_toolkit/tools/utils/source_handling/schema.py +22 -0
- unique_toolkit/tools/utils/source_handling/source_formatting.py +207 -0
- unique_toolkit/tools/utils/source_handling/tests/test_source_formatting.py +215 -0
- {unique_toolkit-0.8.4.dist-info → unique_toolkit-0.8.5.dist-info}/METADATA +4 -1
- {unique_toolkit-0.8.4.dist-info → unique_toolkit-0.8.5.dist-info}/RECORD +19 -10
- unique_toolkit/tools/tool_definitions.py +0 -145
- unique_toolkit/tools/tool_definitionsV2.py +0 -137
- {unique_toolkit-0.8.4.dist-info → unique_toolkit-0.8.5.dist-info}/LICENSE +0 -0
- {unique_toolkit-0.8.4.dist-info → unique_toolkit-0.8.5.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from unique_toolkit.content.schemas import ContentChunk
|
|
3
|
+
from unique_toolkit.tools.utils.source_handling.schema import SourceFormatConfig
|
|
4
|
+
from unique_toolkit.tools.utils.source_handling.source_formatting import (
|
|
5
|
+
_format_page_range,
|
|
6
|
+
format_chunk,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@pytest.fixture
|
|
11
|
+
def default_config():
|
|
12
|
+
return SourceFormatConfig()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@pytest.fixture
|
|
16
|
+
def xml_style_config_without_page_number():
|
|
17
|
+
return SourceFormatConfig(
|
|
18
|
+
source_template="<source${index}>${document}${info}${text}</source${index}>",
|
|
19
|
+
sections={
|
|
20
|
+
"document": "<|document|>{}<|/document|>\n",
|
|
21
|
+
"info": "<|info|>{}<|/info|>\n",
|
|
22
|
+
},
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@pytest.fixture
|
|
27
|
+
def xml_style_config_with_page_number():
|
|
28
|
+
return SourceFormatConfig(
|
|
29
|
+
source_template="<source${index}>${document}${page}${info}${text}</source${index}>",
|
|
30
|
+
sections={
|
|
31
|
+
"document": "<|document|>{}<|/document|>\n",
|
|
32
|
+
"info": "<|info|>{}<|/info|>\n",
|
|
33
|
+
"page": "<|page|>{}<|/page|>\n",
|
|
34
|
+
},
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@pytest.fixture
|
|
39
|
+
def xml_style_config_with_metadata():
|
|
40
|
+
return SourceFormatConfig(
|
|
41
|
+
source_template="<source${index}>${document}${date}${text}</source${index}>",
|
|
42
|
+
sections={
|
|
43
|
+
"document": "<|document|>{}<|/document|>\n",
|
|
44
|
+
"date": "<|DateFromMetaData|>{}<|/DateFromMetaData|>\n",
|
|
45
|
+
},
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@pytest.fixture
|
|
50
|
+
def json_style_config():
|
|
51
|
+
return SourceFormatConfig(
|
|
52
|
+
source_template="{'source_number': ${index}, 'content': '${document}${page}${info}${text}'}",
|
|
53
|
+
sections={
|
|
54
|
+
"document": "<|document|>{}<|/document|>\n",
|
|
55
|
+
"info": "<|info|>{}<|/info|>\n",
|
|
56
|
+
"page": "<|page|>{}<|/page|>\n",
|
|
57
|
+
},
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def test_format_page_range():
|
|
62
|
+
# Test same start and end page
|
|
63
|
+
chunk = ContentChunk(id="1", order=1, text="test", start_page=1, end_page=1)
|
|
64
|
+
assert _format_page_range(chunk) == "1"
|
|
65
|
+
|
|
66
|
+
# Test page range
|
|
67
|
+
chunk = ContentChunk(id="1", order=1, text="test", start_page=1, end_page=3)
|
|
68
|
+
assert _format_page_range(chunk) == "1 - 3"
|
|
69
|
+
|
|
70
|
+
# Test invalid pages
|
|
71
|
+
chunk = ContentChunk(id="1", order=1, text="test", start_page=0, end_page=0)
|
|
72
|
+
assert _format_page_range(chunk) == ""
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def test_json_style_formatting(json_style_config):
|
|
76
|
+
chunk = ContentChunk(
|
|
77
|
+
id="1",
|
|
78
|
+
order=1,
|
|
79
|
+
text="<|document|>Doc1<|/document|>\n<|info|>Important<|/info|>\nContent text",
|
|
80
|
+
start_page=1,
|
|
81
|
+
end_page=2,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
formatted = format_chunk(1, chunk, json_style_config)
|
|
85
|
+
expected = "{'source_number': 1, 'content': '<|document|>Doc1<|/document|>\n<|page|>1 - 2<|/page|>\n<|info|>Important<|/info|>\nContent text'}"
|
|
86
|
+
assert formatted == expected
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def test_metadata_handling(xml_style_config_with_metadata):
|
|
90
|
+
# Test with metadata that matches a section name
|
|
91
|
+
chunk = ContentChunk(
|
|
92
|
+
id="1",
|
|
93
|
+
order=1,
|
|
94
|
+
text="<|document|>Doc1<|/document|>\nContent text",
|
|
95
|
+
metadata={
|
|
96
|
+
"key": "metadata-key",
|
|
97
|
+
"mimeType": "text/plain",
|
|
98
|
+
"date": "12.03.2025",
|
|
99
|
+
}, # type: ignore
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
formatted = format_chunk(1, chunk, xml_style_config_with_metadata)
|
|
103
|
+
expected = "<source1><|document|>Doc1<|/document|>\n<|DateFromMetaData|>12.03.2025<|/DateFromMetaData|>\nContent text</source1>"
|
|
104
|
+
assert formatted == expected
|
|
105
|
+
|
|
106
|
+
# Test with metadata that doesn't match a section name
|
|
107
|
+
chunk = ContentChunk(
|
|
108
|
+
id="1",
|
|
109
|
+
order=1,
|
|
110
|
+
text="<|document|>Doc1<|/document|>\nContent text",
|
|
111
|
+
metadata={
|
|
112
|
+
"key": "metadata-key",
|
|
113
|
+
"mimeType": "text/plain",
|
|
114
|
+
"unrelated_key": "Some value",
|
|
115
|
+
}, # type: ignore
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
formatted = format_chunk(1, chunk, xml_style_config_with_metadata)
|
|
119
|
+
expected = "<source1><|document|>Doc1<|/document|>\nContent text</source1>"
|
|
120
|
+
assert formatted == expected
|
|
121
|
+
|
|
122
|
+
# Test with minimal metadata
|
|
123
|
+
chunk = ContentChunk(
|
|
124
|
+
id="1",
|
|
125
|
+
order=1,
|
|
126
|
+
text="<|document|>Doc1<|/document|>\nContent text",
|
|
127
|
+
metadata={"key": "metadata-key", "mimeType": "text/plain"}, # type: ignore
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
formatted = format_chunk(1, chunk, xml_style_config_with_metadata)
|
|
131
|
+
expected = "<source1><|document|>Doc1<|/document|>\nContent text</source1>"
|
|
132
|
+
assert formatted == expected
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def test_default_style(
|
|
136
|
+
default_config,
|
|
137
|
+
):
|
|
138
|
+
chunk = ContentChunk(
|
|
139
|
+
id="1",
|
|
140
|
+
order=1,
|
|
141
|
+
text="<|document|>Doc1<|/document|>\n<|info|>Important<|/info|>\nContent text",
|
|
142
|
+
start_page=1,
|
|
143
|
+
end_page=2,
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
formatted = format_chunk(1, chunk, default_config)
|
|
147
|
+
expected = "<source1><|document|>Doc1<|/document|>\n<|info|>Important<|/info|>\nContent text</source1>"
|
|
148
|
+
assert formatted == expected
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def test_xml_style_without_page_number_formatting(
|
|
152
|
+
xml_style_config_without_page_number,
|
|
153
|
+
):
|
|
154
|
+
chunk = ContentChunk(
|
|
155
|
+
id="1",
|
|
156
|
+
order=1,
|
|
157
|
+
text="<|document|>Doc1<|/document|>\n<|info|>Important<|/info|>\nContent text",
|
|
158
|
+
start_page=1,
|
|
159
|
+
end_page=2,
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
formatted = format_chunk(1, chunk, xml_style_config_without_page_number)
|
|
163
|
+
expected = "<source1><|document|>Doc1<|/document|>\n<|info|>Important<|/info|>\nContent text</source1>"
|
|
164
|
+
assert formatted == expected
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def test_xml_style_with_page_number_formatting(
|
|
168
|
+
xml_style_config_with_page_number,
|
|
169
|
+
):
|
|
170
|
+
chunk = ContentChunk(
|
|
171
|
+
id="1",
|
|
172
|
+
order=1,
|
|
173
|
+
text="<|document|>Doc1<|/document|>\n<|info|>Important<|/info|>\nContent text",
|
|
174
|
+
start_page=1,
|
|
175
|
+
end_page=2,
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
formatted = format_chunk(1, chunk, xml_style_config_with_page_number)
|
|
179
|
+
expected = "<source1><|document|>Doc1<|/document|>\n<|page|>1 - 2<|/page|>\n<|info|>Important<|/info|>\nContent text</source1>"
|
|
180
|
+
assert formatted == expected
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def test_special_characters_handling(json_style_config):
|
|
184
|
+
chunk = ContentChunk(
|
|
185
|
+
id="1",
|
|
186
|
+
order=1,
|
|
187
|
+
text="<|document|>Doc's \"title\"<|/document|>\n<|info|>Info with {brackets}<|/info|>\nContent: with 'quotes'",
|
|
188
|
+
start_page=1,
|
|
189
|
+
end_page=1,
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
formatted = format_chunk(1, chunk, json_style_config)
|
|
193
|
+
expected = "{'source_number': 1, 'content': '<|document|>Doc's \"title\"<|/document|>\n<|page|>1<|/page|>\n<|info|>Info with {brackets}<|/info|>\nContent: with 'quotes''}"
|
|
194
|
+
assert formatted == expected
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def test_empty_sections(xml_style_config_without_page_number, json_style_config):
|
|
198
|
+
chunk = ContentChunk(
|
|
199
|
+
id="1",
|
|
200
|
+
order=1,
|
|
201
|
+
text="Just plain text without any sections",
|
|
202
|
+
start_page=None,
|
|
203
|
+
end_page=None,
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
# Test XML style
|
|
207
|
+
xml_formatted = format_chunk(1, chunk, xml_style_config_without_page_number)
|
|
208
|
+
assert xml_formatted == "<source1>Just plain text without any sections</source1>"
|
|
209
|
+
|
|
210
|
+
# Test JSON style
|
|
211
|
+
json_formatted = format_chunk(1, chunk, json_style_config)
|
|
212
|
+
assert (
|
|
213
|
+
json_formatted
|
|
214
|
+
== "{'source_number': 1, 'content': 'Just plain text without any sections'}"
|
|
215
|
+
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: unique_toolkit
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.5
|
|
4
4
|
Summary:
|
|
5
5
|
License: Proprietary
|
|
6
6
|
Author: Martin Fadler
|
|
@@ -113,6 +113,9 @@ All notable changes to this project will be documented in this file.
|
|
|
113
113
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
114
114
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
115
115
|
|
|
116
|
+
## [0.8.5] - 2025-08-06
|
|
117
|
+
- Refactored tools to be in the tool-kit
|
|
118
|
+
|
|
116
119
|
## [0.8.4] - 2025-08-06
|
|
117
120
|
- Make unique settings compatible with legacy environment variables
|
|
118
121
|
|
|
@@ -10,7 +10,7 @@ unique_toolkit/app/init_logging.py,sha256=Sh26SRxOj8i8dzobKhYha2lLrkrMTHfB1V4jR3
|
|
|
10
10
|
unique_toolkit/app/init_sdk.py,sha256=5_oDoETr6akwYyBCb0ivTdMNu3SVgPSkrXcDS6ELyY8,2269
|
|
11
11
|
unique_toolkit/app/performance/async_tasks.py,sha256=H0l3OAcosLwNHZ8d2pd-Di4wHIXfclEvagi5kfqLFPA,1941
|
|
12
12
|
unique_toolkit/app/performance/async_wrapper.py,sha256=yVVcRDkcdyfjsxro-N29SBvi-7773wnfDplef6-y8xw,1077
|
|
13
|
-
unique_toolkit/app/schemas.py,sha256=
|
|
13
|
+
unique_toolkit/app/schemas.py,sha256=J584RzwzIVSsdZyq0uVLI6efxIpWiMPKNz_IjIoOrxo,7432
|
|
14
14
|
unique_toolkit/app/unique_settings.py,sha256=Gn8qxy_hNraVTTlP4wfZJzgxPU8cU6s84Uw6FK6ixGg,5946
|
|
15
15
|
unique_toolkit/app/verification.py,sha256=GxFFwcJMy25fCA_Xe89wKW7bgqOu8PAs5y8QpHF0GSc,3861
|
|
16
16
|
unique_toolkit/chat/__init__.py,sha256=LRs2G-JTVuci4lbtHTkVUiNcZcSR6uqqfnAyo7af6nY,619
|
|
@@ -58,10 +58,11 @@ unique_toolkit/language_model/functions.py,sha256=WhgHbJgz4Z2aZt9TLdOpI0PGyYWA5R
|
|
|
58
58
|
unique_toolkit/language_model/infos.py,sha256=Abxcw-l7UXkBohxZsigpNz0OUUCtDf404LLr7R-ys4E,33757
|
|
59
59
|
unique_toolkit/language_model/prompt.py,sha256=JSawaLjQg3VR-E2fK8engFyJnNdk21zaO8pPIodzN4Q,3991
|
|
60
60
|
unique_toolkit/language_model/reference.py,sha256=nkX2VFz-IrUz8yqyc3G5jUMNwrNpxITBrMEKkbqqYoI,8583
|
|
61
|
-
unique_toolkit/language_model/schemas.py,sha256=
|
|
61
|
+
unique_toolkit/language_model/schemas.py,sha256=r6c_lJ9Gl9wvY-N0FlmyFZjv5vPSc6CurFhpyST1Z5Y,14762
|
|
62
62
|
unique_toolkit/language_model/service.py,sha256=zlvC_t9T1wixwcGDPRxl6yYniaKl2725NxWrbW51jUs,11290
|
|
63
63
|
unique_toolkit/language_model/utils.py,sha256=bPQ4l6_YO71w-zaIPanUUmtbXC1_hCvLK0tAFc3VCRc,1902
|
|
64
64
|
unique_toolkit/protocols/support.py,sha256=V15WEIFKVMyF1QCnR8vIi4GrJy4dfTCB6d6JlqPZ58o,2341
|
|
65
|
+
unique_toolkit/reference_manager/reference_manager.py,sha256=FNCW4CQSsimS8UG7OTdu4-JNQXUMhPrOfRuKAbK9vvE,2305
|
|
65
66
|
unique_toolkit/short_term_memory/__init__.py,sha256=2mI3AUrffgH7Yt-xS57EGqnHf7jnn6xquoKEhJqk3Wg,185
|
|
66
67
|
unique_toolkit/short_term_memory/constants.py,sha256=698CL6-wjup2MvU19RxSmQk3gX7aqW_OOpZB7sbz_Xg,34
|
|
67
68
|
unique_toolkit/short_term_memory/functions.py,sha256=3WiK-xatY5nh4Dr5zlDUye1k3E6kr41RiscwtTplw5k,4484
|
|
@@ -69,11 +70,19 @@ unique_toolkit/short_term_memory/schemas.py,sha256=OhfcXyF6ACdwIXW45sKzjtZX_gkcJ
|
|
|
69
70
|
unique_toolkit/short_term_memory/service.py,sha256=5PeVBu1ZCAfyDb2HLVvlmqSbyzBBuE9sI2o9Aajqjxg,8884
|
|
70
71
|
unique_toolkit/smart_rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
71
72
|
unique_toolkit/smart_rules/compile.py,sha256=cxWjb2dxEI2HGsakKdVCkSNi7VK9mr08w5sDcFCQyWI,9553
|
|
72
|
-
unique_toolkit/tools/
|
|
73
|
-
unique_toolkit/tools/
|
|
74
|
-
unique_toolkit/tools/
|
|
75
|
-
unique_toolkit/tools/
|
|
76
|
-
unique_toolkit
|
|
77
|
-
unique_toolkit
|
|
78
|
-
unique_toolkit
|
|
79
|
-
unique_toolkit
|
|
73
|
+
unique_toolkit/tools/agent_chunks_handler.py,sha256=ORjC22ulfHTfPxUHmU7QU0H53j3AdLmt1a0opeI91V8,1809
|
|
74
|
+
unique_toolkit/tools/config.py,sha256=9bYxdDuUPmAxhYyIdLbmXLzX1X2AUw--_WISQxQ4G2U,3003
|
|
75
|
+
unique_toolkit/tools/factory.py,sha256=vxxchbPTrk2lVjSMdpcFN-6FRcMLiy-NgHHS3w0wYCA,1271
|
|
76
|
+
unique_toolkit/tools/schemas.py,sha256=C9caE0EZNS6iGBPz2fsW5_Bao4GGGbAOda5D-XjnAQ0,4743
|
|
77
|
+
unique_toolkit/tools/test/test_tool_progress_reporter.py,sha256=YCR7uJ4_sn-z3CJskzSNWNDYYcThr9m2Q6gRBxbLVfg,6298
|
|
78
|
+
unique_toolkit/tools/tool.py,sha256=Zx9E5YSkzZ_ZUhxLgSLP_iDI8aYGq5wgOahMrnhfNV0,5751
|
|
79
|
+
unique_toolkit/tools/tool_manager.py,sha256=m1yt45rJ0OtC7wLVG5oqf_HvZygC7wV8g9OJWwr4ups,8490
|
|
80
|
+
unique_toolkit/tools/tool_progress_reporter.py,sha256=j6iVTpoLU_PjLwoK6fpIy9vmX_MLWF_-_v-nTDUcwas,7954
|
|
81
|
+
unique_toolkit/tools/utils/execution/execution.py,sha256=vjG2Y6awsGNtlvyQAGCTthQ5thWHYnn-vzZXaYLb3QE,7922
|
|
82
|
+
unique_toolkit/tools/utils/source_handling/schema.py,sha256=pvNhtL2daDLpCVIQpfdn6R35GvKmITVLXjZNLAwpgUE,871
|
|
83
|
+
unique_toolkit/tools/utils/source_handling/source_formatting.py,sha256=C7uayNbdkNVJdEARA5CENnHtNY1SU6etlaqbgHNyxaQ,9152
|
|
84
|
+
unique_toolkit/tools/utils/source_handling/tests/test_source_formatting.py,sha256=zu3AJnYH9CMqZPrxKEH3IgI-fM3nlvIBuspJG6W6B18,6978
|
|
85
|
+
unique_toolkit-0.8.5.dist-info/LICENSE,sha256=GlN8wHNdh53xwOPg44URnwag6TEolCjoq3YD_KrWgss,193
|
|
86
|
+
unique_toolkit-0.8.5.dist-info/METADATA,sha256=LJBjcScwRSwqR65wI1LGrYeoPOBn69r2jCHy2NA0ma0,26245
|
|
87
|
+
unique_toolkit-0.8.5.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
88
|
+
unique_toolkit-0.8.5.dist-info/RECORD,,
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
from abc import ABC, abstractmethod
|
|
2
|
-
from enum import StrEnum
|
|
3
|
-
from typing import Any, Generic, List, Self, TypeVar
|
|
4
|
-
from unique_toolkit.language_model import LanguageModelToolDescription
|
|
5
|
-
from typing_extensions import deprecated
|
|
6
|
-
# import baseModel from pedantic
|
|
7
|
-
from unique_toolkit.language_model import LanguageModelFunction
|
|
8
|
-
from pydantic import BaseModel, Field, model_validator, root_validator
|
|
9
|
-
|
|
10
|
-
from unique_toolkit.unique_toolkit.app.schemas import ChatEvent
|
|
11
|
-
from unique_toolkit.unique_toolkit.tools.tool_progress_reporter import ToolProgressReporter
|
|
12
|
-
|
|
13
|
-
class ToolSelectionPolicy(StrEnum):
|
|
14
|
-
"""Determine the usage policy of tools."""
|
|
15
|
-
|
|
16
|
-
FORCED_BY_DEFAULT = "ForcedByDefault"
|
|
17
|
-
ON_BY_DEFAULT = "OnByDefault"
|
|
18
|
-
BY_USER = "ByUser"
|
|
19
|
-
|
|
20
|
-
class UqToolName(StrEnum):
|
|
21
|
-
WEB_SEARCH = "WebSearch"
|
|
22
|
-
INTERNAL_SEARCH = "InternalSearch"
|
|
23
|
-
DOCUMENT_SUMMARIZER = "DocumentSummarizer"
|
|
24
|
-
CHART_GENERATOR = "ChartGenerator"
|
|
25
|
-
DOCUMENT_GENERATOR = "DocumentGenerator"
|
|
26
|
-
DOCUMENT_PARSER = "DocumentParser"
|
|
27
|
-
IMAGE_CONTENT = "ImageContent"
|
|
28
|
-
TABLE_SEARCH = "TableSearch"
|
|
29
|
-
BAR_CHART = "BarChart"
|
|
30
|
-
LINE_CHART = "LineChart"
|
|
31
|
-
PIE_CHART = "PieChart"
|
|
32
|
-
BASE_TOOL = "BaseTool"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
class BaseToolConfig(BaseModel):
|
|
36
|
-
pass
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
ConfigType = TypeVar("ConfigType", bound=BaseToolConfig)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
class ToolSettings(Generic[ConfigType]):
|
|
43
|
-
configuration: ConfigType
|
|
44
|
-
display_name: str
|
|
45
|
-
icon: str
|
|
46
|
-
selection_policy: ToolSelectionPolicy = Field(
|
|
47
|
-
default=ToolSelectionPolicy.BY_USER,
|
|
48
|
-
)
|
|
49
|
-
is_exclusive: bool = Field(default=False)
|
|
50
|
-
is_enabled: bool = Field(default=True)
|
|
51
|
-
|
|
52
|
-
@classmethod
|
|
53
|
-
def from_service_dict(cls, service_dict: dict[str, Any]) -> Self | None:
|
|
54
|
-
try:
|
|
55
|
-
return cls(**service_dict)
|
|
56
|
-
except (ValueError, TypeError) as e:
|
|
57
|
-
print(e)
|
|
58
|
-
return None
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
class ToolCallResponse(BaseModel):
|
|
62
|
-
id: str
|
|
63
|
-
name: str
|
|
64
|
-
debug_info: dict = {}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
class ToolPromptInstructions(BaseModel):
|
|
68
|
-
system_prompt: str = Field(
|
|
69
|
-
default="",
|
|
70
|
-
description=("Helps the LLM understand how to use the tool. "
|
|
71
|
-
"This is injected into the system prompt."
|
|
72
|
-
"This might not be needed for every tool but some of the work better with user prompt "
|
|
73
|
-
"instructions while others work better with system prompt instructions."),
|
|
74
|
-
)
|
|
75
|
-
|
|
76
|
-
user_prompt: str = Field(
|
|
77
|
-
default="",
|
|
78
|
-
description=("Helps the LLM understand how to use the tool. "
|
|
79
|
-
"This is injected into the user prompt. "
|
|
80
|
-
"This might not be needed for every tool but some of the work better with user prompt "
|
|
81
|
-
"instructions while others work better with system prompt instructions.")
|
|
82
|
-
)
|
|
83
|
-
|
|
84
|
-
system_prompt_tool_chosen: str = Field(
|
|
85
|
-
default="",
|
|
86
|
-
description=("Once the tool is chosen, this is injected into the system prompt"
|
|
87
|
-
" to help the LLM understand how work with the tools results."),
|
|
88
|
-
)
|
|
89
|
-
|
|
90
|
-
user_prompt_tool_chosen: str = Field(
|
|
91
|
-
default="",
|
|
92
|
-
description=("Once the tool is chosen, this is injected into the user prompt "
|
|
93
|
-
"to help the LLM understand how to work with the tools results."),
|
|
94
|
-
)
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
class Tool(ABC, Generic[ConfigType]):
|
|
98
|
-
name: str
|
|
99
|
-
|
|
100
|
-
def tool_description(self) -> LanguageModelToolDescription:
|
|
101
|
-
raise NotImplementedError
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
def get_prompt_instructions(self) -> ToolPromptInstructions:
|
|
105
|
-
return ToolPromptInstructions(
|
|
106
|
-
system_prompt="",
|
|
107
|
-
user_prompt="",
|
|
108
|
-
system_prompt_tool_chosen="",
|
|
109
|
-
user_prompt_tool_chosen="",
|
|
110
|
-
)
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
def is_exclusive(self) -> bool:
|
|
114
|
-
return self.settings.is_exclusive
|
|
115
|
-
|
|
116
|
-
def is_enabled(self) -> bool:
|
|
117
|
-
return self.settings.is_enabled
|
|
118
|
-
|
|
119
|
-
def display_name(self) -> str:
|
|
120
|
-
return self.settings.display_name
|
|
121
|
-
|
|
122
|
-
def icon(self) -> str:
|
|
123
|
-
return self.settings.icon
|
|
124
|
-
|
|
125
|
-
def tool_selection_policy(self) -> ToolSelectionPolicy:
|
|
126
|
-
return self.settings.selection_policy
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
@abstractmethod
|
|
130
|
-
async def run(self, tool_call: LanguageModelFunction) -> ToolCallResponse:
|
|
131
|
-
raise NotImplementedError
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
def __init__(
|
|
136
|
-
self,
|
|
137
|
-
settings: ToolSettings[ConfigType],
|
|
138
|
-
event: ChatEvent,
|
|
139
|
-
tool_progress_reporter: ToolProgressReporter
|
|
140
|
-
):
|
|
141
|
-
self.settings = settings
|
|
142
|
-
self.tool_progress_reporter = tool_progress_reporter
|
|
143
|
-
self.event = event
|
|
144
|
-
|
|
145
|
-
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
from abc import ABC, abstractmethod
|
|
2
|
-
from enum import StrEnum
|
|
3
|
-
from typing import Any, Generic, List, Self, TypeVar
|
|
4
|
-
from unique_toolkit.language_model import LanguageModelToolDescription
|
|
5
|
-
from typing_extensions import deprecated
|
|
6
|
-
# import baseModel from pedantic
|
|
7
|
-
from unique_toolkit.language_model import LanguageModelFunction
|
|
8
|
-
from pydantic import BaseModel, Field, model_validator, root_validator
|
|
9
|
-
|
|
10
|
-
from unique_toolkit.unique_toolkit.app.schemas import ChatEvent
|
|
11
|
-
from unique_toolkit.unique_toolkit.tools.tool_definitions import BaseToolConfig, Tool, ToolCallResponse, ToolPromptInstructions, ToolSettings
|
|
12
|
-
from unique_toolkit.unique_toolkit.tools.tool_progress_reporter import ToolProgressReporter
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class BaseToolConfigV2(BaseToolConfig):
|
|
16
|
-
class ToolCallConfig(BaseModel):
|
|
17
|
-
description: str = Field(
|
|
18
|
-
default="Base",
|
|
19
|
-
description="The tool description must be set by subclasses",
|
|
20
|
-
)
|
|
21
|
-
|
|
22
|
-
parameters: type[BaseModel] = Field(
|
|
23
|
-
default=BaseModel,
|
|
24
|
-
description="The tool parameters configuration must be set by subclasses",
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
class PromptInstructionsConfig(BaseModel):
|
|
28
|
-
system_prompt: str = Field(
|
|
29
|
-
default="",
|
|
30
|
-
description=("Helps the LLM understand how to use the tool. "
|
|
31
|
-
"This is injected into the system prompt."
|
|
32
|
-
"This might not be needed for every tool but some of the work better with user prompt "
|
|
33
|
-
"instructions while others work better with system prompt instructions."),
|
|
34
|
-
)
|
|
35
|
-
|
|
36
|
-
user_prompt: str = Field(
|
|
37
|
-
default="",
|
|
38
|
-
description=("Helps the LLM understand how to use the tool. "
|
|
39
|
-
"This is injected into the user prompt. "
|
|
40
|
-
"This might not be needed for every tool but some of the work better with user prompt "
|
|
41
|
-
"instructions while others work better with system prompt instructions.")
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
system_prompt_tool_chosen: str = Field(
|
|
45
|
-
default="",
|
|
46
|
-
description=("Once the tool is chosen, this is injected into the system prompt"
|
|
47
|
-
" to help the LLM understand how work with the tools results."),
|
|
48
|
-
)
|
|
49
|
-
|
|
50
|
-
user_prompt_tool_chosen: str = Field(
|
|
51
|
-
default="",
|
|
52
|
-
description=("Once the tool is chosen, this is injected into the user prompt "
|
|
53
|
-
"to help the LLM understand how to work with the tools results."),
|
|
54
|
-
)
|
|
55
|
-
|
|
56
|
-
tool_call: ToolCallConfig = Field(
|
|
57
|
-
default_factory=ToolCallConfig,
|
|
58
|
-
description="Configuration for the tool, including description and parameters",
|
|
59
|
-
)
|
|
60
|
-
|
|
61
|
-
prompts: PromptInstructionsConfig = Field(
|
|
62
|
-
default_factory=PromptInstructionsConfig,
|
|
63
|
-
description="Configuration for prompts related to the tool",
|
|
64
|
-
)
|
|
65
|
-
|
|
66
|
-
# This makes sure that the settings are all present in all subclasses and that they define a default value.
|
|
67
|
-
@model_validator(mode="after")
|
|
68
|
-
def validate_tool_description(cls):
|
|
69
|
-
if cls.__class__ is BaseToolConfig:
|
|
70
|
-
return cls # Skip validation for the base class
|
|
71
|
-
if cls.tool_call.description == "Base":
|
|
72
|
-
raise ValueError(
|
|
73
|
-
f"Subclass {cls.__class__.__name__} must define a default value for 'tool_description'."
|
|
74
|
-
)
|
|
75
|
-
if cls.tool_call.parameters == BaseModel:
|
|
76
|
-
raise ValueError(
|
|
77
|
-
f"Subclass {cls.__class__.__name__} must define a default value for 'tool_parameters_config'."
|
|
78
|
-
)
|
|
79
|
-
if cls.prompts.system_prompt == "":
|
|
80
|
-
raise ValueError(
|
|
81
|
-
f"Subclass {cls.__class__.__name__} must define a default value for 'system_prompt_base_instructions'."
|
|
82
|
-
)
|
|
83
|
-
if cls.prompts.user_prompt == "":
|
|
84
|
-
raise ValueError(
|
|
85
|
-
f"Subclass {cls.__class__.__name__} must define a default value for 'user_prompt_base_instructions'."
|
|
86
|
-
)
|
|
87
|
-
if cls.prompts.system_prompt_tool_chosen == "":
|
|
88
|
-
raise ValueError(
|
|
89
|
-
f"Subclass {cls.__class__.__name__} must define a default value for 'system_prompt_tool_chosen_instructions'."
|
|
90
|
-
)
|
|
91
|
-
if cls.prompts.user_prompt_tool_chosen == "":
|
|
92
|
-
raise ValueError(
|
|
93
|
-
f"Subclass {cls.__class__.__name__} must define a default value for 'user_prompt_tool_chosen_instructions'."
|
|
94
|
-
)
|
|
95
|
-
return cls
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
ConfigTypeV2 = TypeVar("ConfigTypeV2", bound=BaseToolConfigV2)
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
class ToolV2(Tool[ConfigTypeV2]):
|
|
103
|
-
name: str
|
|
104
|
-
|
|
105
|
-
def tool_description(self) -> LanguageModelToolDescription:
|
|
106
|
-
return LanguageModelToolDescription(
|
|
107
|
-
name=self.name,
|
|
108
|
-
description=self.settings.configuration.tool_call.description,
|
|
109
|
-
parameters=self.settings.configuration.tool_call.parameters,
|
|
110
|
-
)
|
|
111
|
-
|
|
112
|
-
def get_prompt_instructions(self) -> ToolPromptInstructions:
|
|
113
|
-
return ToolPromptInstructions(
|
|
114
|
-
system_prompt=self.settings.configuration.prompts.system_prompt,
|
|
115
|
-
user_prompt=self.settings.configuration.prompts.user_prompt,
|
|
116
|
-
system_prompt_tool_chosen=self.settings.configuration.prompts.system_prompt_tool_chosen,
|
|
117
|
-
user_prompt_tool_chosen=self.settings.configuration.prompts.user_prompt_tool_chosen
|
|
118
|
-
)
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
@abstractmethod
|
|
122
|
-
async def run(self, tool_call: LanguageModelFunction) -> ToolCallResponse:
|
|
123
|
-
raise NotImplementedError
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
def __init__(
|
|
128
|
-
self,
|
|
129
|
-
settings: ToolSettings[ConfigTypeV2],
|
|
130
|
-
event: ChatEvent,
|
|
131
|
-
tool_progress_reporter: ToolProgressReporter
|
|
132
|
-
):
|
|
133
|
-
self.settings = settings
|
|
134
|
-
self.tool_progress_reporter = tool_progress_reporter
|
|
135
|
-
self.event = event
|
|
136
|
-
|
|
137
|
-
|
|
File without changes
|
|
File without changes
|